2010-02-10 55 views
4

Java泛型和考慮下面的代碼類型擦除

public void example(Object o) { 
    if(o instanceof List<MyType>) 
    //do something 
} 

我明白,這是不可能的(和爲什麼它是不可能的)給定的Java泛型處理和類型擦除方式。

我的問題是,什麼是最好/最乾淨的方式來實現這一目標?或者我唯一能做的就是檢查o是否爲List<?>

+0

這個問題聽起來很熟悉,好像人被要求在過去90天左右。嘗試查看[http://stackoverflow.com/questions/1004022/java-generic-class-determine-type]。 – 2010-02-10 03:19:50

回答

-3

也許通過檢查在運行時的對象類型,也許是這樣的:

if (o.getClass() == List.class) ... 

很明顯,你必須深入挖掘對象的類類型,看它是否是一個精確匹配List<>和列表的元素類型。

+0

在運行時,列表的類與列表完全相同 – 2010-02-10 03:09:58

+1

看起來'List'是一個接口,這可能是一個壞主意 – 2010-02-10 03:13:51

0

短檢查類型列表中所有的項目,它是無法確定Java中的泛型參數的類型,因爲這只是存在在編譯時和運行時之前被移除。

我的建議是,除非你絕對需要讓方法接受一個對象(例如符合接口規範或覆蓋Object.equals),以便將所需的正確類型作爲該方法的參數,並且用可能需要運行該方法的各種其他類型重載該方法。

2

您不能檢查超過o instanceof List<?>

您從Java泛型中獲得的類型安全性僅在編譯時發生。 像你這樣的方法(它接受一個對象,然後試圖弄清楚該怎麼做),在這個設計中效果並不好。 我明白爲什麼這樣一個動態的方法是必要的一段時間,但考慮版本補充它輸入參數:

public void example(Object o) { 
    if(o instanceof List<?>) 
    example((List)o); // can only hope that the type is correct here 
} 

public void example(List<MyType> list){ 
    // do something 
} 

在那些可以使用的情況下,你獲得仿製藥的全部好處。在其他情況下,你必須依靠閱讀你的Javadoc的人,並只傳遞正確的類型。

什麼甚至以上方法不能做的是有List<TypeA>List<TypeB>兩個不同的代碼路徑。如果這對你來說真的需要,可以考慮使用自己的包裝類型ListOfTypeA,ListOfTypeB

取決於你需要做什麼,甚至有可能不會有必要看看刪除類型列表中作爲一個整體,只是在運行時類型的各個元件的工作:

for (Object o: list){ 
    if (o instanceof TypeA){ 
    } 
    if (o instanceof TypeB){ 
    } 
} 
0

Java在編譯後會擦除泛型的類型信息,所以您不能以這種方式動態地檢查類型參數。

如果這個代碼的所有路徑限制類型參數,然後做:

// Return true if object is a list of MyType, false if it is not a list, or is 
// empty 
boolean isListOfMyType(Object o) { 
    if (o instanceof List) { 
     List<?> l = (List<?) o; 
     return (l.size() > 0 && (l.get(0) instanceof MyType) 
    } 
    return true; 
} 

是類型安全的,但如果該列表不爲空時纔會有效。如果不是,您需要修改上述內容以檢查所有項目是否通過了instanceof測試(或者如果您允許列表中有空值,則它們爲空)。

另一種替代方法是創建一個子類,該子類擴展爲ArrayList<MyType>並使用 這表示您的instanceof檢查。

最後但並非最不重要的一個實現List<MyType>的子類將允許您使用Class.getGenericInterfaces()方法獲取類型參數。有關詳細信息,請參見this

對於上述兩種方法中的任何一種,您必須確保創建列表總是實例化這些類型之一。 IE瀏覽器。如果調用者去構建他們自己的ArrayList<MyType>,它將無法工作。