instanceof运算符 - 为什么存在非法编译时错误

时间:2014-09-11 11:08:31

标签: java inheritance interface operator-keyword instanceof

考虑以下代码,我不明白为什么"System.out.println( c2 instanceof D);" 将导致“非法编译时错误”但不返回“false”?非常感谢您的帮助!

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

3 个答案:

答案 0 :(得分:2)

因为编译器知道对类型c2进行转换D总是在运行时失败,因此被标记为编译时错误。所以它不允许这样的instanceof通过。

引用JLS §15.20.2:

  

如果RelationalExpression对ReferenceType的强制转换(第15.16节)将作为编译时错误被拒绝,则关系表达式的实例同样会产生编译时错误。在这种情况下,instanceof表达式的结果永远不会成立。

答案 1 :(得分:1)

Java 8的错误是:

error: incompatible types: C cannot be converted to D

事实上,CD不在同一个血统中(除了Object之外)。由于编译器可以在编译时告诉你instanceof永远不会成立,它确实如此。问题越早发现越好;编译器阻止您拥有不必要的代码或永远不会满足的条件。这就像你得到的代码永远无法达到的错误,因为逻辑是明确的,并且从不允许执行代码(error: unreachable statement)。

这是一个完整的例子:

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);
    }
}

哪个失败了:

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

但是,如果您这样做,编译器无法确定instanceof将始终为false,那么它确实编译并且您在运行时得到false

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);
    }
}

由于我们正在检查的内容o可能是什么,编译器不会提醒您进行不变检查,代码编译,并且您获得false作为输出

答案 2 :(得分:0)

这是因为编译器可以在编译时检查这样的instanceof总是返回false,你可以在JLS中读取它:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2

  

如果将RelationalExpression转换为ReferenceType   作为编译时错误被拒绝,然后是关系实例   表达式同样会产生编译时错误。在这样的   情况,表达式instanceof的结果永远不会   真。

RelationalExpression是第一个操作数,ReferenceType是第二个:RelationalExpression instanceof ReferenceType