2011-08-29 176 views
3

我讀通過莫臥兒(第3版)(最好的SCJP的書,我所遇到的)和727頁上的SCJP,它說以下內容:Java泛型:子類化一個通用的超類 - 子類是一個可定義的類型?

class MyIntList extends ArrayList <Integer> {} // A reifiable subclass 

現在我在這裏只是有點疑惑。我知道子類屬於非泛型類型,但由於它擴展了ArrayList < Integer>和參數化的< Integer>將最終被擦除,並且此子類將繼承其超類的屬性,爲什麼這個子類MyIntList是可重用類型?

+0

無論如何,這種區分在這種情況下如何重要?很明顯,新的MyIntList().getClass()== MyIntList.class'不會丟失任何信息(因爲還有什麼可能呢?) - 它是否正確地將單詞「reifiable」賦值給它還是不? –

+1

您似乎認爲在這種情況下,'MyIntList'會在運行時將其超類參數''擦除。不是這種情況。泛型類的具體子類保留其超類泛型參數的類型信息。這使得一些[非常漂亮的技巧]成爲可能(http://gafter.blogspot.com/2006/12/super-type-tokens.html)。 –

+0

@亨寧,想想所有的工具,測試等可以寫在一個約束列表。 –

回答

3

因爲MyIntList的每個實例都是Array<Integer>,所以可以使用反射來找出下限/上限。

如果您說class MyNumberList<T extends Number> extends ArrayList<T> { ... },您仍然可以找到邊界,但不是T對於MyNumberList的特定實例。

+0

但參數化的已被刪除 – yapkm01

+3

@ yapkm01:不是。泛型類型的特定參數化的非泛型子類型沒有刪除該參數化。 –

+0

@ yapkm01構建直覺的一種方法是考慮*實例*。如果你有一個'ArrayList'的實例,你不知道'T'是什麼。但是每個MyIntList實例總是一個ArrayList 。換句話說,Java不會創建一個對應於你的'ArrayList '的新'Class'。但是參數類型被烘焙到'MyIntList'的'Class'中。 –

3

從Java語言規範 http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html

4.7 Reifiable類型

由於某些類型的信息在編譯時擦除,不是所有類型的都可以在運行時。運行時完全可用的類型稱爲可重用類型。只有在以下情況之一成立的情況下,類型纔可認證:

  • 它引用了非泛型類型聲明。
  • 它是一個參數化類型,其中所有類型參數都是無界通配符(§4.5.1)。
  • 它是一種原始類型(§4.8)。
  • 它是一種原始類型(§4.2)。
  • 它是一個數組類型(§10.1),其組件類型是可調整的。
0

泛型類型在編譯ArrayList期間被擦除,但不在編譯MyIntList期間被擦除。所以在運行時你可以通過調用MyIntList.class.getGenericSuperclass()並分析返回的對象來發現MyIntList擴展了ArrayList。

這是可能的原因是MyIntList本身不是通用的,但擴展了ArrayList的具體實例。所以這些信息可以存儲在MyIntList的Class對象中(使用上面提到的方法可以訪問它)。

相關問題