In the SCJP book by Kathey Sierra, an excerpt is as follows:
If a method is overridden but you use a polymorphic (supertype) reference to refer to
When you look at the code, you can realize: when the object you invoke eat() on is
Because of that, the second usage results in the compiler complaining to you.
Overriding a method and to reduce the throws signature is perfectly fine. A caller that knows how to deal with an exception for sure works when a sub class never throws.
The compiler doesn't know the real type of the object referenced. It only checks that assignments are valid.
The call to a.eat
causes a compile error because the compiler doesn't know the Animal referenced by a is a Dog2. It is deciding whether a checked exception can be thrown based solely on the type of the variable referencing the Dog2.
The compiler is not smart. It does not run the code and it does not keep track of the actual class of the object assigned to the variable a
.
Just as when you refer to an object with the type of its superclass you won't see methods specific to the subclass, you also see the throws-clause of the superclass, not that of the subclass's method.
If you add a cast to the subclass in the last line:
((Dog2)a).eat();
then you won't get the unreported exception compile error.