Alfonso Saenz wrote:According what I have read is the object type who determines the method. Then.. Since object is Lizard, why invokes Reptile method?

It's a trick question Only methods which are inherited can be overridden. And private methods are never inherited and thus can never be overridden. Repeat after me: private methods are never inherited and thus can never be overridden! So the layEggs() method in class Lizard seems to be overriding the layEggs() method in class Reptile, but that's not true. In fact, because the layEggs() method in class Reptile is private, class Lizard doesn't know class Reptile has a layEggs() method. And if you don't know about a method, you definitely can't override it.
Because the type of the reference variable reptile is Reptile and the layEggs() method in class Reptile is not overridden (for the aforementioned reason), the layEggs() method in class Reptile is simply executed (no polymorphism is happening here). If you remove the private access modifier from the layEggs() method in class Reptile, you'll get the output you were expecting.

Alfonso Saenz wrote:Thanks in advance and sorry for my ignorance.

No need to apologize! We are all here to learn and improve our (Java) knowledge.

Alfonso Saenz wrote:but I thought that as a hidden method, was the lizard's which is invoked.

The type of the actual object (to which a reference variable is refering) only matters if a method is overridden and at runtime the JVM needs to decide which method will be executed (= polymorphism). In all other cases, which method (or field) will be invoked (or accessed) is determined based on the reference variable type.

in this case, method eat() in Animal is public, so... it is overridden in Lion with same signature and return type.
In this case both objects are Lion() and both will print the output given by Lion's method.

There is another issue with Exceptions. NotHungryException is not declared or treated in main()

Alfonso Saenz wrote:In this case both objects are Lion() and both will print the output given by Lion's method.

There is another issue with Exceptions. NotHungryException is not declared or treated in main()

You are correct! Have a cow for not getting fooled by my contrived code snippet

And this code snippet illustrates again that the reference variable determines which method can be invoked. So although reference variable a refers to a Lion object and we know that a lion is always hungry and will never throw a NotHungryException, the compiler only sees the reference variable type (which is Animal) and thus only these methods can be invoked. Because the eat() method might throw a checked exception, the compiler forces you to handle or declare this checked exception. And if you don't meet this requirement (with the current code snippet), you'll get a compiler error.
If the NotHungryException is handled or declared (using one of your proposed changes), the code will compile and "lion always hungry!" will be printed twice.

If you take good care of your cattle, you can milk her twice a day and enjoy some fresh milk

Just like on Facebook, you can the post(s) which you liked. So other ranchers will see immediately which are the "starred" posts. But for awesome, very helpful,... posts someone can award you a cow (that's much better than +1). If you would like to know more about the ranch cows, you can read the Ranch Cows article.

As you mentioned that the reference variable determines the method to be invoked, you mean in

'a' being a reference of Animal goes to eat() present in the Animal class, then checks on the access specifiers - which is public hence it knows it can be inherited. Now as 'a' points to the object of Lion class and eat() can be inherited, goes and checks in Lion class. JVM finds the eat() in Lion and hence executes "Lion is always hungry".

Hope i am right.
If my understanding is right, what would happen if 'a' after realizing that eat() can be inherited, checks in Lion but doesn't find any eat() then it comes back to Animal and executes eat() of Animal?

Vani Dasu wrote:'a' being a reference of Animal goes to eat() present in the Animal class, then checks on the access specifiers - which is public hence it knows it can be inherited. Now as 'a' points to the object of Lion class and eat() can be inherited, goes and checks in Lion class. JVM finds the eat() in Lion and hence executes "Lion is always hungry".

Hope i am right.

Yes, you are! And there's another implication as well. Although the actual object denoted by reference variable a is Lion and thus you know (checked) NotHungryException will never be thrown, you still have to handle-or-declare this exception. And that's because the compiler only knows about the type of the reference variable a, which is Animal and its eat() method has the (checked) NotHungryException in its throws clause.

Vani Dasu wrote:If my understanding is right, what would happen if 'a' after realizing that eat() can be inherited, checks in Lion but doesn't find any eat() then it comes back to Animal and executes eat() of Animal?

Yes, that's exactly what will happen. In this post and the next one, I have given a detailed explanation about the process to determine which method should be invoked for two similar scenarios (one with a private method and another one with an overridden method).