2010-10-23 39 views
27

考慮:爲什麼我會得到「instanceof非法通用類型」?

public class C<T> { 
    private class D { 
     public boolean equals(Object o) { 
      if (!(o instanceof D)) // line 4 
       return false; 
      D other = (D)o;    // line 6 
      return i == other.i; 
     } 
     int i; 
    } 
} 

我得到:

C.java:4: illegal generic type for instanceof 
      if (!(o instanceof D)) 
          ^

我也得到一個 「未投」 警告約6行麼? o而不是通用類型 - 它只是一個普通的Object。如何通過檢查和鑄造D的實例來正確執行equals()

注:顯然,這個代碼示例是我的實際代碼的削減版本。 CD的真實類別要大得多,而DCprivate內部類別。

供參考:真正的D確實使用通用參數T

+7

你試過*的instanceof C.D *而不是*的instanceof d *? – 2010-10-23 00:59:28

+0

我只是要指出,給出*的例子*被打破。 – 2010-10-23 01:00:09

+0

@Evan:行之有效。但爲什麼資格是必要的? – 2010-10-23 01:09:02

回答

30

的o是不是一個泛型類型 - 它只是一個普通的對象。

這不是問題所在。問題......和編譯錯誤的根本原因...... D是一個泛型類。它是通用的,因爲它是泛型類中的非靜態嵌套類。其完全合格的名稱將是some.pkg.C<T>.D

FYI:真正的d確實使用泛型參數T.

而事實上,它可能利用T是什麼使D泛型類的。

您不能使用instanceof D(D)的原因是通用類型擦除。基本上,運行時不能區分(說)C<String>.DC<Integer>.D的類型。並且由於它不能這樣做,所以它不能確定instanceof D應該返回true還是false或者(D)應該成功或丟棄ClassCastException

一種解決方案是宣佈D爲靜態。但是這不適用於你的「真正的D」,因爲靜態類不能使用封閉類中的泛型類型參數。你的「供參考」說它是這樣做的。

另一種解決方案是實例化外部類C,將實際類型T作爲java.lang.Class<T>實例傳遞給它。然後使用這個Class實例來實現運行時類型檢查並根據需要進行強制轉換。這很可能是凌亂的。

第三種解決方案是仔細地分析代碼並確定@SuppressWarning註釋是否安全以抑制「不安全轉換」等警告。

什麼類型的擦除? 'o'是Object的類型。

實際上Object聲明類型o可變的。實際的對象很可能有其他類型,並且它是,即類型(例如,如果它是例如D實例)將進行類型擦除。

7

如果你讓內部類是靜態的,代碼編譯得很好。

例:

private static class D{...} 

閱讀here的差異。

你也可以嘗試o.getClass() != D.class(後防範o爲空,當然)

+0

我知道非靜態和靜態嵌套類之間的區別。在這種情況下,我需要它是非靜態的。如果我使嵌套類靜態,我不能使用通用參數T. – 2010-10-23 01:05:40

+1

o.getClass()和D.class比較怎麼辦?你不會知道它們具有相同的參數化類型,但我不確定你是否可以通過類型擦除來可靠地完成此操作。 – 2010-10-23 01:07:03

+0

什麼類型的擦除? 'o'是Object的類型。 – 2010-10-23 01:12:29

3
D.class.isInstance(o) 

似乎在這裏工作。

6

@StephenC是正確的,問題是D意味着C<T>.D,這是一個參數化類型。該解決方案是使用原始類型或通配符參數化類型:

if (!(o instanceof C.D)) 

if (!(o instanceof C<?>.D)) 
相關問題