[英]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
你是什么意思? 當然會產生錯誤。
舉個例子: SomeObject
是Fruit
,你有2個派生類Apple
和Orange
你的清單包含哪些內容? Apple
s還是Orange
s? 編譯器無法分辨。 所以它會產生錯誤。
如果你替換List<? extends SomeObject> l
使用List<SomeObject> l
List<? extends SomeObject> l
List<SomeObject> l
。 然后這將起作用,因為Apple
和Orange
都是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.