[英]generic VS wildcards in Java
我在泛型類下有這兩種方法:
public class Container<S> {
public void f2(List<Object> l1, List<?> l2) {
l1 = l2; //compilation error row #1
}
public void f3(List<?> c, List<S> l) {
c = l; //ok row #2
l = c; //compilation error row #3
}
}
我真的不小心,為什么第2行是好的 - 如果我將這個方法轉移到兩個列表,一個是對象類型列表,一個是字符串一個,我收到編譯錯誤?
我真的很想知道為什么每行應該/不應該編譯。
為什么編譯?
List<?> c, List<S> l;
c = l; // OK
List<?>
表示(或多或少)“某事物列表”(或更正式的“未知列表”), List<S>
就是其中之一。
-
為什么這不編譯?
List<Object> l1, List<?> l2;
l1 = l2; //compilation error
如果允許,則可以向l1
添加任何內容(例如String),但如果l2
不是List<Object>
(例如Integer),則在l2
輸入錯誤的類型。 這就是為什么不允許這項任務的原因。
另一個編譯錯誤更微妙,也沒有用例 - 也就是說,沒有理由將類型列表分配給無類型的 - 但是通配符?
真的意思是“未知,但具體 ”。 這與“任何事情”都不一樣。 這是“某事”,但我們不知道是什么。 類型S
是某種東西,但編譯器無法驗證它與S
是否相同 。
泛型和通配符是強大的,因為它們確保在編譯期間更好的類型檢查,這是使用它們的主要目的。 確保您的代碼在運行時不會因類型檢查不良而中斷。
盡管Integer是Number的子類型,但
List<Integer>
不是List<Number>
的子類型,實際上,這兩種類型不相關。List<Number>
和List<Integer>
的公共父是List<?>
。為了在這些類之間創建關系以便代碼可以通過
List<Integer>
的元素訪問Number
的方法,請使用上限的通配符:List<? extends Integer> intList = new ArrayList<>(); List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
因為
Integer
是Number
的子類型,而numList
是Number
對象的列表,所以intList
(Integer
對象列表)和numList
之間現在存在關系。 下圖顯示了使用上限和下限通配符聲明的多個List類之間的關系。
要使用通配符的子類型和多態性,必須使用有界通配符 。
public void f2(List<Object> l1, List<?> l2) {
l1 = l2; //compilation error row #1
}
//correct way of doing it
public void f2(List<? extends Object> l3, List<?> l4) {
l3 = l4;
}
編譯器沒有將l2視為l1的子類型
public void f3(List<?> c, List<S> l) {
c = l; //ok row #2
l = c; //compilation error row #3
}
編譯器沒有將c視為l的子類型(正確地說,這可能導致運行時錯誤)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.