泛型原始型別
原始型別是沒有任何型別引數的泛型類或介面的名稱,例如,給定Box
泛型類:
public class Box<T> {
public void set(T t) { /* ... */ }
// ...
}
要建立引數化型別的Box<T>
,請為形式型別引數T
提供實際型別引數:
Box<Integer> intBox = new Box<>();
如果省略實際的型別引數,則建立一個原始型別Box<T>
:
Box rawBox = new Box();
因此,Box
是泛型Box<T>
的原始型別,但是,非泛型類或介面型別不是原始型別。
原始型別出現在遺留程式碼中,因為許多API類(例如Collections
類)在JDK 5.0之前不是泛型的,使用原始型別時,你實際上獲得預泛型行為 — Box
會為你提供Object
,為了向後相容,允許將引數化型別分配給其原始型別:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox; // OK
但是,如果將原始型別分配給引數化型別,則會收到警告:
Box rawBox = new Box(); // rawBox is a raw type of Box<T>
Box<Integer> intBox = rawBox; // warning: unchecked conversion
如果使用原始型別呼叫相應泛型型別中定義的泛型方法,也會收到警告:
Box<String> stringBox = new Box<>();
Box rawBox = stringBox;
rawBox.set(8); // warning: unchecked invocation to set(T)
警告顯示原始型別繞過泛型型別檢查,將不安全程式碼的捕獲延遲到執行時,因此,你應該避免使用原始型別。
型別消除部分提供了有關Java編譯器如何使用原始型別的更多資訊。
未經檢查的錯誤訊息
如前所述,在將遺留程式碼與泛型程式碼混合時,你可能會遇到類似於以下內容的警告訊息:
Note: Example.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
在使用對原始型別進行操作的舊API時會發生這種情況,如以下示例所示:
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
static Box createBox(){
return new Box();
}
}
術語“unchecked”表示編譯器沒有足夠的型別資訊來執行確保型別安全所必需的所有型別檢查,預設情況下,“unchecked”警告被禁用,儘管編譯器會提示,要檢視所有“unchecked”警告,請使用-Xlint:unchecked
重新編譯。
使用-Xlint:unchecked
重新編譯上一個示例顯示以下附加資訊:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
要完全禁用使用-Xlint:-unchecked
標誌的未經檢查的警告,@SuppressWarnings("unchecked")
註解會抑制未經檢查的警告,如果你不熟悉@SuppressWarnings
語法,請參閱註解。