【问题标题】:instanceof operator - why there is Illegal compile time errorinstanceof 运算符 - 为什么存在非法编译时错误
【发布时间】:2014-11-05 07:26:00
【问题描述】:

考虑到下面的代码,我不明白为什么"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));
  • CD 是同一继承层次结构的叶子,因此彼此不相关 - 在编译时可以检查。
  • 谢谢。好吧,这是一个学校练习,我应该解释错误发生的原因。

标签: java inheritance interface operator-keyword instanceof


【解决方案1】:

Java 8 的错误是:

错误:不兼容的类型:C 无法转换为 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:错误:不兼容的类型:C 不能转换为 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】:

    那是因为编译器可以在编译时检查 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

    【讨论】:

      【解决方案3】:

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

      引用JLS §15.20.2:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-13
        • 2017-04-08
        • 1970-01-01
        • 2012-08-13
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        相关资源
        最近更新 更多