[英]Java Generics Difference between List of Wildcard and List of Box of Wildcard?
為什么是
List<?> list = new ArrayList<Object>();
同時
List<Box<?>> boxList = new ArrayList<Box<Object>>();
不被允許
還有List<? extends Box<?>>
List<? extends Box<?>>
意思。
因為List<Box<?>>
接受包含任何內容的框。 因此,以下內容有效:
List<Box<?>> boxes = new ArrayList<>();
boxes.add(new Box<Integer>());
boxes.add(new Box<String>());
而List<Box<Object>>
僅接受Box<Object>
實例。 由於Box<Integer>
和Box<String>
不是Box<Object>
,因此以下內容無效。
List<Box<Object>> boxes = new ArrayList<>();
boxes.add(new Box<Integer>());
boxes.add(new Box<String>());
現在,如果您的問題是“為什么Box<String>
不是Box<Object>
”,那么答案是,如果是,則可以執行以下操作,這將破壞泛型類型的類型安全性:
Box<Integer> boxOfIntegers = new Box<>();
Box<Object> box = boxOfIntegers; // this is actually invalid
box.add("I'm a string in a box of integers. Ouch!");
您的問題是一個經典的通用難題。 通常,我們的大腦足夠聰明,可以從已知規則中推斷出新規則,但對於泛型而言並非如此。 您的問題說明了通配符的兩個常見問題:
List<Box<Object>>
分配給List<Box<?>>
List<Box<?>>
上調用add()
,而不能在List<?>
上調用 第一個問題的解決方案是泛型是不變的:無論將什么類型賦予類型變量,都沒有子類型關系,除非涉及通配符。 即使Box<Object>
是Box<?>
的子類型,該子類型關系也不適用於封閉列表。
問題2的規則是不遞歸捕獲通配符。 實際上, new ArrayList<Box<?>>()
是有效的表達式,而new ArrayList<?>()
不是。 另外,正如我之前所說,您可以將元素添加到List<Box<?>>
因為通用類型List<E>
的實例化會產生:
// This actually doesn't compile, it's just an explanation of the
// instantiation process
public interface List<Box<?>> {
void add(Box<?> box);
}
List<A>
是List<?>
的子類型,其中A
是一種類型(滿足通配符的范圍,如果有的話)。
但是,如果A
和B
是不同的類型(不管A
和B
之間A
任何子類型關系),則List<A>
不是List<B>
子類型。
您可能已經看到List<String>
不是List<Object>
的子類型的情況,即使String
是Object
的子類型。 (我不會在這里討論原因。)
即使Box<String>
是Box<?>
的子類型,如果List<Box<String>>
不是List<Box<?>>
的子類型,也會發生同樣的事情。 請注意,即使有一個?
在某處,它是Box<?>
類型的一部分在內部深處。 ?
不會在List
的參數級別上起作用,因此不允許您采用其他類型的列表。
如果要使用可以接受List<Box<String>>
和List<Box<Integer>>
等的類型,則可能要使用List<? extends Box<?>>
List<? extends Box<?>>
。 請注意,這里有一個?
在頂層。 這使List
的類型參數可以是Box<?>
任何子類型,包括Box<String>
和Box<Integer>
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.