Nat*_*H06 1 generics lambda list generic-list java-8
对于设置,我有:
interface Parent
interface Child1 extends Parent
interface Child2 extends Parent
Run Code Online (Sandbox Code Playgroud)
我在其他地方:
public class MyClass {
private List<Child1> child1List = new ArrayList<>();
public List<Parent> getChild1List(Contact contact) {
return child1List.parallelStream()
.filter(m -> m.getContacts().contains(contact))
.sorted(Comparator.comparing(Parent::getParentField))
.collect(Collectors.toList());
}
}
Run Code Online (Sandbox Code Playgroud)
当我这样做时,getChild1List返回一个List<Parent>(不应该返回List<Child1>吗?)
后来,我发现该流对其他方法很有用,所以我提取它并用它构建了一个泛型方法.我有多个扩展Parent的接口,所以我做了如下:
private <T extends Parent> List<T> returnsListByContact(List<T> childList, Contact contact) {
return childList.parallelStream()
.filter(m -> m.getContacts().contains(contact))
.sorted(Comparator.comparing(Parent::getParentField))
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
并getChild1List(Contact contact)成为:
public List<Parent> getChild1List(Contact contact) {
return returnsListByContact(child1List, contact);
}
Run Code Online (Sandbox Code Playgroud)
但是现在它不喜欢这个,引用getChild1List返回一个List<Child1>.我不明白为什么,因为流的实现根本没有改变 - 除了启动它的childList来自通用参数,而不是直接调用MyClass的私有成员字段.
那他们为什么要回归两件不同的东西呢?
(这个例子令人困惑.Meeting真的Parent吗?)
在的第一个版本getChild1List,所述collect(toList())方法被称为上Stream<Child1>和它的目标类型-通过的返回类型确定getChild1List-是List<Parent>.这是有效的,因为它允许T超类型的收集器收集类型为T的流.更具体地说,您将类型的实例添加Child1到List<Parent>类型安全且允许的类型中.您也可以改变getChild1List()返回的声明List<Child1>而不是List<Parent>.
您可以通过查看collect()in 的声明来查看允许差异的位置Stream<T>:
<R,A> R collect(Collector<? super T,A,R> collector)
Run Code Online (Sandbox Code Playgroud)
这? super T是允许方差的原因.
你的声明returnsListByContact,
<T extends Parent> List<T> returnsListByContact(List<T> childList, ...)
Run Code Online (Sandbox Code Playgroud)
并没有允许偏差.它需要一个类型的参数List<T>并返回一个List<T>.参数和返回类型必须相同.这就是为什么当你传入一个List<Child1>并且尝试从返回类型为的方法返回它时不匹配的原因List<Parent>- 那些类型是不兼容的.
要解决此问题,您需要在声明中添加一些差异returnsListByContact.这是我如何做到的:
<T extends Parent> List<T> returnsListByContact(List<? extends T> childList, ...)
Run Code Online (Sandbox Code Playgroud)
这允许您在传递某个子类型的列表时返回某种类型的列表,在这种情况下,在List<Parent>传入时返回List<Child1>,这是我认为您想要的.