3 回答

TA貢獻1804條經(jīng)驗 獲得超8個贊
您可能知道謂詞是兼容的,但編譯器不兼容。
想象一下這個例子:
Predicate<? extends Collection<Object>> p1 = (Set<Object> s) -> s.isEmpty();
Predicate<? extends Collection<Object>> p2 = (List<Object> l) -> l.get(0) != null;
我們開發(fā)人員可以看到,第一個謂詞在技術(shù)上可以處理所有集合,而第二個謂詞只能處理列表。但是想象一下謂詞在其他地方被初始化或者同時被改變。編譯器無法確定謂詞對象是為哪種類型的集合創(chuàng)建的。因此,您根本無法使用它們:
Set<Object> set = new HashSet<>();
List<Object> list = new ArrayList<>();
p1.test(set);
p2.test(list);
p1.test(list);
p2.test(set);
所有這些調(diào)用都不會編譯,因為編譯器無法確定背后的實際對象p1和p2can 是否完全適用于這些類型的集合。這就是意思? extends Collection<>:你知道它是一個特定的子類型,但你不能告訴編譯器究竟是哪一個。
用一個更簡單的例子來說明這一點:
Collection<Apple> appleBasket = ...;
appleBasket.add(new Apple()); // works
appleBasket.add(new Orange()); // does not work (obviously)
Collection<Fruit> mixedFruitBasket = ...;
mixedFruitBasket.add(new Apple()); // works
mixedFruitBasket.add(new Orange()); // works
// Now the tricky part
Collection<? extends Fruit> unknownButPureFruitBasket = ...;
unknownButPureFruitBasket.add(new Apple()); // does not work
unknownButPureFruitBasket.add(new Orange()); // does not work
您不能將任何一種水果添加到您不知道其類型的籃子中。事實上,它可能是一個可以容納所有水果的籃子,但也可能是一個純蘋果籃子、橙色籃子,甚至是你還不知道的香蕉籃子。
在您的 IDE 中嘗試:
List<? extends String> l1 = new ArrayList<>();
List<? extends String> l2 = new ArrayList<>();
l1.addAll(l2);
Eclipse 告訴我:
類型 List<capture# 1 -of 中的addAll(Collection1-of ? extends String>) 方法 extends String> 不適用于參數(shù) (List<capture# 2 -of ? extends String>)
請注意不同的類型:addAll期望是 的集合capture#1,l2是 的集合capture#2。

TA貢獻1847條經(jīng)驗 獲得超7個贊
filter
需要一個Predicate<? super TestObject>
,而不是Predicate<? extends TestObject>
。
為什么super TestObject
?因為這里的 TestObject 是一個輸入?yún)?shù),一個消費者。根據(jù)PECS規(guī)則,它應(yīng)該被標(biāo)記為super。
Predicate<? extends TestObject>
完全不同于Predicate<? super TestObject>
.?前者可以接受TestObject
and 的所有子類TestObject
。后者可以接受的所有超TestObject
和TestObject
。顯然,它們是不同的且不兼容的。

TA貢獻1893條經(jīng)驗 獲得超10個贊
這實際上與 Java 如何處理謂詞無關(guān),而只是泛型問題。
簡而言之,答案是predicate和predicate1不一定兼容。參數(shù)的類型or為Predicate<? super T>,假設(shè)T在兩個Predicate對象中是相同的具體類型參數(shù)。但這種情況并非如此。
為了說明問題,假設(shè):
class TestObject2 extends TestObject {
boolean isTrue() {
return true;
}
}
class TestObject3 extends TestObject {
boolean isTrue3() {
return true;
}
}
并且(注意聲明的類型沒有改變,但實際的 lambda 表達式改變了):
private static Predicate<? extends TestObject> predicate =
(TestObject2 testObject) -> testObject.isTrue();
private static Predicate<? extends TestObject> predicate1 =
(TestObject3 testObject) -> testObject.isTrue3();
在這個例子中,or會得到錯誤的值(predicate接受一個TestObject2對象,但在這種情況下,它可以用一個TestObject3對象調(diào)用)。
你認(rèn)為predicate1這會如何工作filter?
Stream.of(new TestObject2(), new TestObject2()).filter(predicate.or(predicate1));
事實是,編譯器低保Predicate<? extends TestObject>是既兼容Predicate<TestObject2>和Predicate<TestObject3>(這是按照仿制藥的法律)
添加回答
舉報