簡體   English   中英

java泛型邊界

[英]java generics bounds

我有以下代碼:

public <T extends SomeObject> long doSomething(T someObject){
    List<? extends SomeObject> l = new LinkedList<>();
    l.add(someObject);
}

這會導致編譯錯誤 - 告訴我找不到合適的方法:add(T),為什么會這樣?

如果l接受擴展的東西SomeObject不應該接受someObject因為它SomeObject擴展SomeObject

List<? extends SomeObject> l

你是什​​么意思? 當然會產生錯誤。

舉個例子: SomeObjectFruit ,你有2個派生類AppleOrange

你的清單包含哪些內容? Apple s還是Orange s? 編譯器無法分辨。 所以它會產生錯誤。

如果你替換List<? extends SomeObject> l 使用List<SomeObject> l List<? extends SomeObject> l List<SomeObject> l 然后這將起作用,因為AppleOrange都是Fruit

我建議你使用這個聲明:

List<T> l = new LinkedList<T>();

這樣就不那么類型安全了

List<SomeObject> l = new LinkedList<SomeObject>();

此外,您還可以從列表中獲取類型為T的對象,而無需進行強制轉換。 T已經是SomeObject所以不需要在T上調用SomeObject的方法進行轉換。所有這些都少了輸入!

回到問題所在。

首先要注意的是通配符類型“?” 意思是未知 ,這很重要。 但是,您可以為其指定上限(?extends)或下限(?super)。 您將列表聲明為“列表”。

已知List中包含SomeObject的對象。 但! 對象的確切類型未知。

編譯器不能說列表中是否存在“A類擴展SomeObject”或“B類擴展SomeObject”的實例。 如果調用list.get(),它只能說會有SomeObject類型的對象。

SomeObject obj = list.get(1);   // Ok

但是插入任何(!)類型的對象是不安全的,因為列表中的實際元素類型是未知的。

您可能想知道為什么存在通配符類型。 這是為了降低類型鑄造中的限制,否則將過於嚴格。

樣品

class A { }

class A2 extends A { }

class B <T> {
    void change(T a) { .. };
    T read() { ..  };
}

如果沒有通配符,我們將無法執行此操作: B<A> b = new B<A2>(); - 這是行不通的。 這是因為從B<A> to B<A2>類型轉換是不安全的。

為什么? 我們來看看(復制自http://en.wikipedia.org/wiki/Generics_in_Java

List<Integer> ints = new ArrayList<Integer>();
ints.add(2);
List<Number> nums = ints;  // valid if List<Integer> were a subtype of List<Number>
nums.add(3.14);  
Integer x = ints.get(1);   // now 3.14 is assigned to an Integer variable!

解決辦法是什么? 有時,我們希望以一般方式進行此類分配或傳遞參數!

通配符類型有助於: B<? extends A> b = new B<A2>(); B<? extends A> b = new B<A2>(); 方法B.void change(T a)現已禁用 - 這是您的問題在第一部分中解釋和解釋。

方法BT read()仍然有效並返回A: A a = b.read(); 是的,它實際上返回A2但是對於b.read()的調用者它是可見的A.

通配符類型在Collections Framework中廣泛使用。

暫無
暫無

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

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