[英]Java Generic type : difference between List <? extends Number> and List <T extends Number>
[英]Java Generic List<List<? extends Number>>
為什么java中我們做不到:
List<List<? extends Number>> aList = new ArrayList<List<Number>>();
即使這樣也可以:
List<? extends Number> aList = new ArrayList<Number>();
編譯器錯誤消息是:
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
在Java中,如果Car
是派生類Vehicle
,那么我們可以將所有Cars
視為Vehicles
; Car
是一種Vehicle
。 但是, Cars
List
也不是Vehicles
List
。 我們說List<Car>
是不是有協 List<Vehicle>
。
Java要求您明確告訴它何時使用協方差和逆向通配符,由?
表示?
令牌。 看看你的問題發生在哪里:
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------- ------
//
// "? extends Number" matched by "Number". Success!
內部List<? extends Number>
List<? extends Number>
works,因為Number
確實擴展了Number
,所以它匹配“ ? extends Number
”。 到現在為止還挺好。 下一步是什么?
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------------- ------------
//
// "List<? extends Number>" not matched by "List<Number>". These are
// different types and covariance is not specified with a wildcard.
// Failure.
但是,組合內部類型參數List<? extends Number>
List<? extends Number>
與List<Number>
不匹配; 類型必須完全相同 。 另一個通配符將告訴Java這個組合類型也應該是協變的:
List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();
我對Java語法不是很熟悉,但似乎你的問題是:
你一定要用? 在適當的時候鍵入通配符,不要將其作為一般規則來避免。 例如:
public void doThingWithList(List<List<? extends Number>> list);
允許您傳遞List<Integer>
或List<Long>
。
public void doThingWithList(List<List<Number>> list);
允許您只傳遞聲明為List<Number>
。 一個小的區別,是的,但使用通配符是強大而安全的 。 與它看起來相反, List<Integer>
不是List<Number>
的子類,也不是可分配的。 List<Integer>
也不是List<? extends Number
的子類List<? extends Number
List<? extends Number
,這就是上面代碼無法編譯的原因。
你的語句沒有編譯,因為List<? extends Number>
List<? extends Number>
與List<Number>
類型不同。 前者是后者的超類型。
你試過這個嗎? 這里我表示List在其類型參數中是協變的,因此它將接受List<? extends Number>
任何子類型List<? extends Number>
List<? extends Number>
(包括List<Number>
)。
List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();
甚至這個。 這里右側的ArrayList的類型參數與左側的類型參數相同,因此方差不是問題。
List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
你應該可以說
List<List<Number>> aList = new ArrayList<List<Number>>();
我傾向於避免?
盡可能輸入通配符。 我發現類型注釋中產生的費用不值得。
List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
aList.add(new ArrayList<Integer>());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.