Kendall Ponder wrote:So the compiler can't tell the difference between code snippets until the code runs.
The compiler is not involved when the code is ran. That's why you have javac (the
java compiler) to compile your classes and java to run your classes. The compiler makes sure you don't do things which are forbidden (like trying to cast a
Cat to a
Dog). If you do something forbidden, you'll get a compiler error (and no class file). So the compiler does NOT care what happens at runtime, it's only interested in what it knows at compile time.
In this code snippet:
the compiler doesn't care to which object reference variable
a is referring to, it's only interested in the type of the reference variable. In
line2 the compiler doesn't have any knowledge about the type of the actual object reference variable
a is referring to. It only knows the type of
a is
Animal and because
Dog extends
Animal, the compiler allows this cast, because
a could refer to a
Dog object. The same applies to
line3: the compiler doesn't know anything about the type of the actual object reference variable
d, it only knows that the type of
d is
Dog and because
Dog and
Cat are siblings (and thus not in the same class hierarchy), there is NO way
d can refer to a
Cat object and therefore you'll get a compiler error on
line3. Hope that makes sense!
And this code really illustrates why the compiler doesn't care about what happens at runtime:
Now the compiler simply can't know to which object reference variable
a will be referring to, because it depends on a command line parameter when the program is ran. But you can only run the program if it's compiled! But the compiler will still do a bunch of checks: e.g. is the type of reference variable
a compatible with the return type of method
createAnimal; is the type of every return value compatible with the return type of method
createAnimal;...
Kendall Ponder wrote:Which means it allows a casting from any class in a hierarchy to any other class in the hierarchy because it is possible for it to be legal. Right?
No! It all depends if both class belong to the same class hierarchy. If both classes belong to a different class hierarchy (like Cat and Dog; String and Integer; Cat and String;...) you'll get a compiler error if you try to cast. If classes belong to the same class hierarchy (like Object, Animal and Cat; Object, Throwable, Exception, RuntimeException and IllegalArgumentException;...) you won't get a compiler error but you risk a runtime ClassCastException when the type and the actual object are not compatible. More info about different class hierarchies and its consequences can be found in
this thread. Note: it's about the
instanceof operator, but the same rules apply to casting as well. And if interfaces are involved, it gets even a little trickier. More info in
this thread.
Hope it helps!
Kind regards,
Roel