3 回答

TA貢獻1833條經驗 獲得超4個贊
它們中的每一個都存在差異,我將解釋其中的大部分。讓我們從我們的例子開始。我使用這個類層次結構:
class Food {}
class Apple extends Food {}
class Orange extends Food {}
class RedApple extends Apple {}
List<Food> listFood = new ArrayList<>();
List<Apple> listApple = new ArrayList<>();
List<Orange> listOrange = new ArrayList<>();
List<RedApple> listRedApple = new ArrayList<>();
現在從第一個開始:
A. public static <T> List<T> backwards(List<T> input)
這個方法只會接受List<T>和返回List<T>,你不能發送listApple和返回listRedApple。(但是您的返回列表可以包含,RedApple因為它擴展Apple但列表類型必須是List<Apple>,沒有別的)
B. public static <T> List<T> backwards(List<? extends T> input)
您可以發送listRedApple和返回,listApple但您知道這listRedApple是“?擴展 Apple”,因此在方法主體中 java 將 T 識別為 Apple。然后,如果你使用可以添加的元素listRedApple,其發送作為參數,你可以添加Apple在listRedApple其中是不正確的!所以編譯器避免它并給出編譯錯誤。在 B 中,您只能讀取元素(并將其作為 T 獲?。荒芟蚱渲刑砑尤魏蝺热?。
C. public static <T> List<T> backwards(List<? super T> input)
您可以發送listApple,然后在方法主體中添加任何擴展,Apple因為編譯器將 T 視為 TApple的任何列表,并且在T的任何超列表中,您可以添加任何擴展Apple。
但是這一次,您無法讀取任何內容,因為您不知道它的類型,除非您將其作為Object. (這是一個“?超級T”的列表)
正如你在這里看到的,有區別嗎?超級和?延伸。其中之一為您提供寫訪問權限,另一個為您提供讀訪問權限。這就是通配符的真正用途。
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
如果您發送listApple然后您返回,List<? extends Apple>但您可以將它分配給任何listFood或listApple或listRedApple因為List<? extends Apple>可能包含Apple或RedApple或其他東西,我們不能將它分配給任何List<T>因為然后我們可以添加T到該列表中,并且可能T和? extends T不一樣。這對D和都是一樣的E。您可以將其分配給List<? extends Apple>for 'E 和List<? super Apple>forD并將它們發送到需要它們作為參數的方法。
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
給出編譯錯誤,因為不能像這樣使用通配符。
我希望這對你有幫助。
如果有什么問題,任何評論都表示贊賞。

TA貢獻1780條經驗 獲得超1個贊
選項D和E是有效的,因為泛型類型之間存在超子類型關系,允許您定義方法可以接受或返回的更大的類型集。
因此,以下是有效的 (D):
public static <T> List<? extends T> backwards(List<T> input) {
return List.of();
}
// there exist a super-subtype relationships among List<? extends Number> and List<Long>
List<? extends Number> list = backwards(List.<Long>of(1L, 2L));
因為該類型Long是通配符所? extends Number表示的類型家族的成員(作為其子類型的類型家族Number和類型Number本身)。
下一個代碼片段也是有效的 (E):
public static <T> List<? super T> backwards(List<T> input) {
return List.of();
}
List<? super Long> ints = backwards(List.<Long>of(1L, 2L));
因為該類型Long是通配符所? super Long表示的類型家族的成員(作為超類型的類型家族Long和類型Long本身)。
所以,你的理解是對的。

TA貢獻1876條經驗 獲得超7個贊
下圖描述了泛型中的子類型關系:
List<T> is a subtype of List<? super T>
Also List<T> is a subtype of List<? extends T>
這就是為什么選項 D 和 E 是正確的。
您可以參考該頁面:https : //docs.oracle.com/javase/tutorial/java/generics/subtyping.html
添加回答
舉報