2014-09-11 106 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)); 
    } 
} 
相關問題