[英]Java generics and type erasure
給出以下代碼:
public void example(Object o) {
if(o instanceof List<MyType>)
//do something
}
我了解,鑒於Java處理泛型和類型擦除的方式,這是不可能的(以及為什么不可能如此)。
我的問題是,最佳/最干凈的方法是什么? 還是我唯一能做的就是檢查o
是否為List<?>
?
您最多只能檢查一次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
,請考慮使用自己的包裝器類型ListOfTypeA
, ListOfTypeB
。
根據您需要執行的操作,甚至可能根本沒有必要查看列表的已擦除類型,而只需要處理單個元素的運行時類型即可:
for (Object o: list){
if (o instanceof TypeA){
}
if (o instanceof TypeB){
}
}
如果不檢查List中所有項目的類型,就無法確定Java中通用參數的類型,因為它僅在編譯時存在,並在運行時刪除。
我的建議是,除非您絕對需要使該方法接受一個Object(例如符合接口規范或重寫Object.equals),然后將所需的正確類型作為該方法的參數,並使用您可能需要使用其他各種類型來運行該方法。
Java在編譯后會刪除泛型的類型信息,因此您不能以這種方式動態檢查類型參數。
如果此代碼的所有路徑都限制了type參數,請執行以下操作:
// 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 test(如果列表中允許為null,則它們是否為null)。
另一種選擇是創建一個擴展了ArrayList<MyType>
的子類,並將其用於您的instanceof
檢查。
最后但並非最不重要的是,有一個實現List<MyType>
的子類將使您可以使用Class.getGenericInterfaces()
方法獲得type參數。 請參閱此了解詳情。
對於這兩種最后一種方法,您必須確保列表的創建始終實例化這些類型之一。 就是 如果調用方去構建自己的ArrayList<MyType>
,它將無法正常工作。
也許通過在運行時檢查對象類型,也許像:
if (o.getClass() == List.class) ...
顯然,您必須更深入地研究對象的類類型,以查看它是否與List<>
和列表的元素類型完全匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.