instanceof运算符-为什么会出现非法编译时错误

4
考虑以下代码,我不明白为什么"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();`

尝试使用 System.out.println("" + (c2 instanceof D)); - EpicPandaForce
CD是同一继承层次结构的叶子节点,因此它们彼此之间没有关联 - 这可以在编译时进行检查。 - Smutje
谢谢。好的,这是一项学校练习,我应该解释错误发生的原因。 - user3735871
3个回答

2

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: 不兼容的类型: 无法将 C 转换为 D
        System.out.println(c2 instanceof D);

但是,如果您让编译器无法确定instanceof始终为假,那么代码确实可以编译,并在运行时获得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
因为编译器知道将c2强制转换为类型D总是会在运行时失败,因此标记为编译时错误。因此,它不允许这样的instanceof通过。
引用JLS §15.20.2: 如果将关系表达式强制转换为ReferenceType(§15.16)会被拒绝作为编译时错误,则instanceof关系表达式同样会产生编译时错误。在这种情况下,instanceof表达式的结果永远不能为真。

0

这是因为编译器可以在编译时检查到这样的instanceof总是返回false,您可以在JLS中阅读相关内容:

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

如果将RelationalExpression的强制类型转换为ReferenceType会被拒绝作为编译时错误,那么instanceof关系表达式同样会产生编译时错误。在这种情况下,instanceof表达式的结果永远不可能为真。其中,RelationalExpression是第一个操作数,ReferenceType是第二个操作数:RelationalExpression instanceof ReferenceType

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接