簡體   English   中英

通用類型擦除警告

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM