簡體   English   中英

Java泛型之間的通配符列表和通配符框列表之間的區別?

[英]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是一種類型(滿足通配符的范圍,如果有的話)。

但是,如果AB是不同的類型(不管AB之間A任何子類型關系),則List<A>不是List<B>子類型。

您可能已經看到List<String>不是List<Object>的子類型的情況,即使StringObject的子類型。 (我不會在這里討論原因。)

即使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.

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