Why don't I get a compilation error in the code below?
Because the compiler only cares about the static type of the expression you're trying to cast.
Look at these two lines:
BlackInk blackInk = new BlackInk();
printable = (Printable)blackInk;
You know that in the second line, the value blackInk
only refers to an object of type BlackInk
due to the first line, but the compiler doesn't. For all the compiler knows (when compiling the second line) it could actually have been:
BlackInk blackInk = new PrintableBlackInk();
printable = (Printable)blackInk;
... where PrintableBlackInk
is a class extending BlackInk
and implementing Printable
. Therefore it's valid (at compile-time) to cast from an expression of type BlackInk
to Printable
. If you make BlackInk
a final
class, then the compiler knows that there's no way that it will work (unless the value is null) and will fail at compile-time, like this:
error: inconvertible types
printable = (Printable)blackInk;
^
required: Printable
found: BlackInk
The details for this are in JLS 5.5.1.
Otherwise, we have to wait until execution time to see the failure, because the cast is valid at compile-time.
BlackInk
norInk
isPrintable
, how (or rather why) does the compiler approve the cast? – LogoblackInk
could be a reference to an instance of a class extendingBlackInk
and implementingPrintable
. It compiles for the same reason thatObject o = new Object(); String x = (String) o;
compiles... – Mountbatten