Search code examples
javainheritanceinterfaceoperator-keywordinstanceof

instanceof operator - why there is Illegal compile time error


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();`

Solution

  • 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.