[英]Upper-Bounded and Lower-Bounded Wildcards in return type of Java Generic method
[英]Lower-Bounded Wildcards Java - Access to Methods
我理解,存在低限通配符的一個原因是,在添加新元素時,集合不是不可變的。
例如
List<? extends Number> obj = new ArrayList<>();//Now this list is immutable
obj.add(new Integer(5));//Does not compile
List<? super Number> objTwo = new ArrayList<>();//This list is mutable
objTwo.add(new Integer(5));//Compiles
以下不編譯因為我試圖得到數字的長值。
Q1:我可以使用哪些方法? 只有Objects方法?:
public void testLowerBounds(List<? super Number> numbers){
if (!numbers.isEmpty()){
System.out.println(numbers.get(0).longValue());//Does not compile
}
}
我的問題是如何產生的:我目前正在學習流,本書指定了以下流方法:
Optional<T> min(Comparator<? super T> comparator)
並實現如下:
Stream<String> s = Stream.of("monkey", "ape", "bonobo");
Optional<String> min = s.min((s1, s2) -> s1.length()—s2.length());
Q2:比較器在使用時如何允許使用字符串方法?
如果我必須回答Q2:我會說可選是指定“你必須傳遞一個具有泛型類型”字符串“的比較器的實現或者實現”字符串“的東西。我會說這個是正確的嗎?
期待你的回復。
首先,您不應將通配符類型參數與可變性混淆。 在List
的元素類型中使用通配符不會阻止修改,它只對您可以對列表執行的操作施加一些實際限制。
將列表聲明為List<? extends Number>
List<? extends Number>
意味着引用列表具有的實際的元件類型Number
或子類Number
,例如,它可能是一個List<Integer>
或List<Double>
。 因此,您無法添加任意Number
實例,因為您無法知道它是否與實際元素類型兼容。
但是您仍然可以添加null
,因為已知null
引用與所有引用類型兼容。 此外,您始終可以從列表中刪除元素,例如調用remove
或clear
而不會出現問題。 您還可以調用Collections.swap(list, index1, index2)
,這很有意思,因為有關通配符類型的正式規則調用list.set(index1, list.get(index2))
是不合法的,但是將列表傳遞給另一個可能使用非通配符類型變量來表示列表元素類型的方法。 這顯然是正確的,因為它只設置源自同一列表的元素,這些元素必須兼容。
同樣,如果你有一個Comparator<Number>
,你可以調用Collections.sort(list, comparator)
作為一個可以處理任意數字的比較器,能夠處理列表中實際存儲的任何數字。
總結一下,有? extends
? extends
在集合的元素類型並不妨礙修改。
如上所述,您不能將任意新元素插入到實際元素類型可能是綁定的未知子類的List<? extends Number>
,例如List<? extends Number>
List<? extends Number>
。 但是您可以保證在檢索元素時獲得Number
實例,因為Number
每個子類型實例也是Number
的實例。 當你聲明一個List<? super Number>
List<? super Number>
,它的實際元素類型可能是Number
或超類型的Number
,例如Object
或Serializable
。 您可以插入任意Number
實例,因為您知道它將與列表具有的任何實際元素類型兼容,因為它是超類型的數字。 檢索實例時,您只知道它是Object
的實例,因為它是所有實例的超類型。 要比較? extends
? extends
案例,有一個? super
? super
聲明不會阻止閱讀,它只會帶來一些實際限制。 同樣,你仍然可以將它傳遞給Collections.swap
,因為無論我們對實際類型知之甚少,插入我們剛從同一列表中檢索到的內容都可行。
在你的第二個問題中,你讓雙方感到困惑。 你現在不是在看min
的實現,而是在調用者處 。 min(Comparator<? super T> c)
允許調用者傳遞任何使用T
或超類型T
參數化的比較器。 所以當你有一個Stream<String>
,將Comparator<String>
傳遞給min
方法是有效的,這正是你通過(s1, s2) -> s1.length()—s2.length()
lambda表達式(但是,我更喜歡Comparator.comparingInt(String::length)
)。
在min
的實現中,確實不知道Comparator
T
或實際類型參數是什么。 但是,知道任何類型為T
流元素都可以傳遞給比較器的compare
方法,這可能需要T
或超類型的T
,這就足夠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.