2014-09-11 45 views
2

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

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

尝试'的System.out.println( “” +(C2的instanceof d)); ' – EpicPandaForce 2014-09-11 11:10:18

+0

'C'和'D'是具有相同继承层次的叶子,因此彼此不相关 - 在编译时可检查。 – Smutje 2014-09-11 11:11:13

+0

谢谢。那么这是一个学校练习,我应该解释错误发生的原因。 – user3735871 2014-09-11 11:12:06

回答

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

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:

如果RelationalExpression到引用类型的铸造(§15.16)将被拒绝作为一个编译时间错误,那么的instanceof关系式同样产生一个编译时间错误。在这种情况下,表达式实例的结果永远不会是真的。

+0

JLS引用+1! – 2014-09-11 11:18:59

0

那是因为编译器可以在编译时检查,这样instanceof总是返回false,你可以在JLS上写着:

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

如果RelationalExpression的强制转换为引用类型将 作为编译时错误拒绝,则关系表达式的实例同样会产生编译时错误。在这样一个 的情况下,instanceof表达式的结果永远不可能是 。

RelationalExpression是第一操作数和引用类型是第二:RelationalExpression instanceof ReferenceType

-1

和以下工作:

public class C extends B { 

    public static void main(String[] args) { 
     C c2 = new C(); 
     System.out.println(D.class.isInstance(c2)); 
    } 
} 
相关问题