[英]Generic Type Erasure Warning
我從Thinking in Java一書中得到了這個代碼,Bruce在調用方法set()時指出了警告。 代碼如下:
package testPackage;
class GenericBase<T> {
private T element;
public void set(T arg) { arg = element; }
public T get() { return element; }
}
class Derived1<T> extends GenericBase<T> {}
class Derived2 extends GenericBase {} // No warning
// class Derived3 extends GenericBase<?> {}
// Strange error:
// unexpected type found : ?
// required: class or interface without bounds
public class ErasureAndInheritance {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Derived2 d2 = new Derived2();
Object obj = d2.get();
d2.set(obj); // Warning here!
}
}
如果我刪除注釋,我會收到以下警告:
類型安全:方法集(Object)屬於原始類型GenericBase。 應參數化對泛型類型GenericBase的引用
我的問題是,為什么警告顯示在set()方法上? 有人可以解釋一下這個警告意味着什么嗎?
順便說一句,我是Java Generics的新手,雖然我讀了關於泛型的其他問題,但我仍然對Erasure感到困惑。
來自Java doc 這里
泛型被引入到Java語言中,以便在編譯時提供更嚴格的類型檢查並支持泛型編程。 為了實現泛型,Java編譯器將類型擦除應用於:
- 如果類型參數是無界的,則將泛型類型中的所有類型參數替換為其邊界或對象。 因此,生成的字節碼僅包含普通的類,接口和方法。
- 如有必要,插入類型鑄件以保持類型安全。
- 生成橋接方法以保留擴展泛型類型中的多態性。
- 類型擦除確保不為參數化類型創建新類; 因此,泛型不會產生運行時開銷。
簡單:在編譯過程之后,每個泛型都是一個Object
,它只是為您添加了轉換,如果您做錯了,它將生成編譯器錯誤。
關於unchecked
注釋,當編譯器無法確定您正在做什么是正確的時使用它(事實上,您使用的原始類型與GenericBase<Object>
)
除了類型T
之外,你有自set
方法以來的警告但由於你使用的是原始類型,它不知道T
是什么,並生成此警告以告知您正在使用原始類型(壞事)。
您可以使用注釋來說:“我知道它是原始類型,但我知道它是合法的,我知道我在做什么”。
混合原始類型和泛型類型是可能的,因為泛型的實現方式,如上所述,在編譯器處理之后, T
變為Object
,這意味着像GenericBase
這樣的原始對象與GenericBase<T>
。
它沒有要求使用泛型的任何轉換的原因是因為它將為您添加轉換(並且您可以確保代碼將始終在運行時工作而不用擔心可能的ClassCastException
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.