instanceof operator - why there is Illegal compile time error

后端 未结 3 1919
情书的邮戳
情书的邮戳 2021-01-06 16:19

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 \

相关标签:
3条回答
  • 2021-01-06 16:57

    The error from Java 8 is:

    error: incompatible types: C cannot be converted to D

    And indeed, C and D are not in the same lineage (other than both being Object). Since the compiler can tell you at compilation time that the instanceof 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:

    public class Example {
    
        interface I { }
        static class A { int x = 1;}
        static class B extends A implements I { int y = 2;}
        static class C extends B { }
        static class D extends B{ }
        static class E implements I { }
    
        public static final void main(String[] args) {
            C c2 = new C();
            System.out.println(c2 instanceof D);
        }
    }
    

    Which fails with:

    Example.java:12: error: incompatible types: C cannot be converted to D
            System.out.println(c2 instanceof D);

    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 get false at runtime:

    public class Example {
    
        interface I { }
        static class A { int x = 1;}
        static class B extends A implements I { int y = 2;}
        static class C extends B { }
        static class D extends B{ }
        static class E implements I { }
    
        public static final void main(String[] args) {
            C c2 = new C();
            doTheCheck(c2);
        }
    
        static void doTheCheck(Object o) {
            System.out.println(o instanceof D);
        }
    }
    

    Since what we're checking, o, could be anything, the compiler doesn't alert you to the invariant check, the code compiles, and you get false as output.

    0 讨论(0)
  • 2021-01-06 17:02

    Because compiler knows that casting c2 to type D will always doing to fail at runtime, and hence is marked as compile time error. So it doesn't allow such instanceof to pass through.

    Quoting JLS §15.20.2:

    If a cast (§15.16) of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.

    0 讨论(0)
  • 2021-01-06 17:06

    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

    If a cast of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.

    RelationalExpression is first operand, and ReferenceType is second: RelationalExpression instanceof ReferenceType

    0 讨论(0)
提交回复
热议问题