簡體   English   中英

Java中的通用VS通配符

[英]generic VS wildcards in Java

我在泛型類下有這兩種方法:

public class Container<S> {
    public void f2(List<Object> l1, List<?> l2) {
        l1 = l2; //compilation error row #1
    }

    public void f3(List<?> c, List<S> l) {
        c = l; //ok row #2
        l = c; //compilation error row #3
    }
}

我真的不小心,為什么第2行是好的 - 如果我將這個方法轉移到兩個列表,一個是對象類型列表,一個是字符串一個,我收到編譯錯誤?

我真的很想知道為什么每行應該/不應該編譯。

為什么編譯?

List<?> c, List<S> l;
c = l; // OK

List<?>表示(或多或少)“某事物列表”(或更正式的“未知列表”), List<S>就是其中之一。

-

為什么這不編譯?

List<Object> l1, List<?> l2;
l1 = l2; //compilation error

如果允許,則可以向l1添加任何內容(例如String),但如果l2不是List<Object> (例如Integer),則在l2輸入錯誤的類型。 這就是為什么不允許這項任務的原因。

另一個編譯錯誤更微妙,也沒有用例 - 也就是說,沒有理由將類型列表分配給無類型的 - 但是通配符? 真的意思是“未知,但具體 ”。 這與“任何事情”都不一樣。 這是“某事”,但我們不知道是什么。 類型S是某種東西,但編譯器無法驗證它與S是否相同

泛型和通配符是強大的,因為它們確保在編譯期間更好的類型檢查,這是使用它們的主要目的。 確保您的代碼在運行時不會因類型檢查不良而中斷。

資源

盡管Integer是Number的子類型,但List<Integer>不是List<Number>的子類型,實際上,這兩種類型不相關。 List<Number>List<Integer>的公共父是List<?>

為了在這些類之間創建關系以便代碼可以通過List<Integer>的元素訪問Number的方法,請使用上限的通配符:

 List<? extends Integer> intList = new ArrayList<>(); List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number> 

因為IntegerNumber的子類型,而numListNumber對象的列表,所以intListInteger對象列表)和numList之間現在存在關系。 下圖顯示了使用上限和下限通配符聲明的多個List類之間的關系。

要使用通配符的子類型和多態性,必須使用有界通配符

public void f2(List<Object> l1, List<?> l2) {
  l1 = l2; //compilation error row #1
}

//correct way of doing it
public void f2(List<? extends Object> l3, List<?> l4) {
  l3 = l4; 
}

編譯器沒有將l2視為l1的子類型

public void f3(List<?> c, List<S> l) {
  c = l; //ok row #2
  l = c; //compilation error row #3
}

編譯器沒有將c視為l的子類型(正確地說,這可能導致運行時錯誤)。

暫無
暫無

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

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