Considering the following code, I don't understand why "System.out.println( c2 instanceof D);"
will result an "illegal compile time error" but not return "false"? Many thanks for your help!
interface I { }
class A { int x = 1;}
class B extends A implements I { int y = 2;}
class C extends B { }
class D extends B{ }
class E implements I { }
C c2 = new C();`
Because compiler knows that casting
c2
to typeD
will always doing to fail at runtime, and hence is marked as compile time error. So it doesn't allow suchinstanceof
to pass through.Quoting JLS §15.20.2:
Thats because compiler can check at compile time that such
instanceof
would always return false, you can read on it in JLS:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2
RelationalExpression is first operand, and ReferenceType is second:
RelationalExpression instanceof ReferenceType
The error from Java 8 is:
And indeed,
C
andD
are not in the same lineage (other than both beingObject
). Since the compiler can tell you at compilation time that theinstanceof
will never be true, it does. The earlier a problem is caught, the better; the compiler is preventing your having code that is unnecessary or a condition that will never be satisfied. It's like the error you get when you have code that can never be reached because the logic is unambiguous and never allows execution of the code (error: unreachable statement
).Here's a complete example:
Which fails with:
But, if you make it so the compiler can't know for sure that the
instanceof
will always be false, then it does indeed compile and you getfalse
at runtime:Since what we're checking,
o
, could be anything, the compiler doesn't alert you to the invariant check, the code compiles, and you getfalse
as output.