簡體   English   中英

為什么在 java generics 列表中<integer>是 List 的子類型<!--? extends Integer--> ?</integer>

[英]Why in java generics List<Integer> is a subtype of List<? extends Integer>?

在 java 教程中:

https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

它表示List<Integer>List<? extends Integer> List<? extends Integer> ,我覺得這違反直覺,因為? extends Integer ? extends Integer表示任何類型是IntegerInteger的子類型,這背后的設計考慮是什么?

引用:

https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html

術語List<Number>List<? extends Number> List<? extends Number>因為前者只匹配 Number 類型的列表,而后者匹配 Number 類型或其任何子類的列表。

我也對List<? super Number> List<? super Number>List<? super Integer> List<? super Integer>

在此處輸入圖像描述

考慮到List<Dog> 是 List<Animal> 的子類,我很驚訝竟然存在超類型/子類型關系? 為什么 Java generics 不是隱式多態的? . 但是,既然有,我只能冒險自己的想法/猜測為什么它被允許以及為什么這樣。

編輯添加:進一步檢查,我不應該感到驚訝,因為關系與狗和動物相同 - 即。 List<Animal>List<? extends Animal> List<? extends Animal>

話雖如此,我想這是為了保持對這些列表的其他引用“安全”。 例如,考慮一些可能的情況:

public class PositiveInteger extends Integer {

那么我們可以有

List<Integer> listInteger = new ArrayList<>();
List<Integer> myIntegers = listInteger;
List<PositiveInteger> listPositiveInteger = new ArrayList<>();
List<PositiveInteger> myPositives = listPositiveInteger;

現在,超類型和子類型的想法是我們可以將子類型引用分配給超類型,但反之則不行。 例如我們可以有:

Animal animal = myDog;

但不是

Dog rex = someAnimal;

因此,讓我們將該邏輯應用於我們的列表。

List<? extends Integer> positives = listInteger;

正如你所說,這是允許的。 需要注意的重要一點是,我們現有的myIntegers變量是安全的——它仍然只會包含Integer

此語句的唯一“危險”是這允許positives.get(0)可能收到負數 Integer - 但這根本不是真正的危險(只是我們變量命名的問題),因為這里的語言語法僅指對於整數,與 PositiveIntegers 無關。 就語言而言,我們同樣可以:

List<? extends Integer> positives = new ArrayList<NegativeIntegers>();

現在,如果我們允許:

List<Integer> integers = listPositiveInteger;

現在系統的這部分是安全的——但是我們的myPositives變量呢??? myPositives的所有用戶都完全有權期望只收到 PositiveIntegers,但沒有什么能阻止我們擁有:

integers.add(-123);

由於這是與 myPositives 相同的列表myPositives ,因此我們將 -123 添加到該列表 - 一個更加危險的前景隱含影響系統的 rest。

為什么在 java generics List<Integer>List<? extends Integer> List<? extends Integer> ?

因為否則您將無法執行以下操作:

List<Integer> list1 = new ArrayList<>();
List<? extends Integer> list2 = list1;

就個人而言,我會發現上述導致錯誤是反直覺的情況。 當你有List<? extends Integer> List<? extends Integer>就是說List可能包含IntegerInteger 1的某些子類型,或Integer的子類型的混合物 List<Integer>當然滿足這些要求。

List<? super Number> List<? super Number>List<? super Integer> List<? super Integer>非常相似。 如果不是這種情況,那么您將無法執行以下操作:

List<? super Number> list1 = new ArrayList<>();
List<? super Integer> list2 = list1;

所有List<? super Integer> List<? super Integer>表示List能夠使用 Integer 類型的IntegerInteger的某些超類型。 一個List<? super Number> List<? super Number>滿足這些要求。

以下是一些可能有用的鏈接:

我建議也瀏覽上述問答的鏈接/相關部分。


1. 說“ Integer的子類型”可能會令人困惑,因為 class 是final的,但希望它仍然有意義。

試試看? super T 像這樣的? super T子類型:

<? super Number> <? super Number><Number><Serializable><Object>的通配符

<? super Integer> <? super Integer><Integer><Number><Serializable><Object>的通配符

Integer可以放在所有可能的<? super Number> <? super Number>所以<? super Integer> <? super Integer>可以是<? super Number> <? super Number> (是一種關系,所以<? super Number><? super Integer>的子類型)

Number不能放在所有可能的<? super Integer> <? super Integer> (你不能在Integer預期的地方放任何Number )所以<? super Number> <? super Number>不能是<? super Integer> <? super Integer>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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