流中的泛型参数returns List<ChildInterface>,但直接方法调用returns List<Parent>
Generic parameter returns List<ChildInterface> in stream, but direct method call returns List<Parent>
对于设置,我有:
interface Parent
interface Child1 extends Parent
interface Child2 extends Parent
在其他地方我有:
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());
}
}
当我这样做时,getChild1List return是一个List<Parent>
(不应该是return 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());
}
和getChild1List(Contact contact)
变成:
public List<Parent> getChild1List(Contact contact) {
return returnsListByContact(child1List, contact);
}
但现在它不喜欢这样,引用 getChild1List 是 returning a List<Child1>
。我不明白为什么,因为流的实现根本没有改变——除了启动它的 childList 通过通用参数,而不是直接调用 MyClass 的私有成员字段。
那么为什么他们 return 是两种不同的东西?
(这个例子很混乱。Meeting
真的是Parent
吗?)
在 getChild1List
的第一个版本中,collect(toList())
方法在 Stream<Child1>
及其目标类型上调用——由 return 类型决定 getChild1List
——是List<Parent>
。这是有效的,因为它允许类型 T 的流由 T 的超类型的收集器收集。更具体地说,您将类型 Child1
的实例添加到 List<Parent>
类型 -安全并被允许。您也可以将 getChild1List()
的声明更改为 return List<Child1>
而不是 List<Parent>
.
您可以通过查看 Stream<T>
中 collect()
的声明来了解允许差异的位置:
<R,A> R collect(Collector<? super T,A,R> collector)
? super T
允许差异。
您对 returnsListByContact
、
的声明
<T extends Parent> List<T> returnsListByContact(List<T> childList, ...)
不允许差异。它采用 List<T>
和 return 类型的参数 List<T>
。参数和 return 类型必须相同。这就是为什么当您传入 List<Child1>
并尝试从 return 类型为 List<Parent>
的方法 return 时出现不匹配的原因——这些类型不兼容。
要解决此问题,您需要在 returnsListByContact
的声明中添加一些差异。这是我的做法:
<T extends Parent> List<T> returnsListByContact(List<? extends T> childList, ...)
这允许您在传递某些子类型的列表时 return 某种类型的列表,在这种情况下 returning List<Parent>
同时传递 List<Child1>
,这就是我想你想要的。
对于设置,我有:
interface Parent
interface Child1 extends Parent
interface Child2 extends Parent
在其他地方我有:
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());
}
}
当我这样做时,getChild1List return是一个List<Parent>
(不应该是return 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());
}
和getChild1List(Contact contact)
变成:
public List<Parent> getChild1List(Contact contact) {
return returnsListByContact(child1List, contact);
}
但现在它不喜欢这样,引用 getChild1List 是 returning a List<Child1>
。我不明白为什么,因为流的实现根本没有改变——除了启动它的 childList 通过通用参数,而不是直接调用 MyClass 的私有成员字段。
那么为什么他们 return 是两种不同的东西?
(这个例子很混乱。Meeting
真的是Parent
吗?)
在 getChild1List
的第一个版本中,collect(toList())
方法在 Stream<Child1>
及其目标类型上调用——由 return 类型决定 getChild1List
——是List<Parent>
。这是有效的,因为它允许类型 T 的流由 T 的超类型的收集器收集。更具体地说,您将类型 Child1
的实例添加到 List<Parent>
类型 -安全并被允许。您也可以将 getChild1List()
的声明更改为 return List<Child1>
而不是 List<Parent>
.
您可以通过查看 Stream<T>
中 collect()
的声明来了解允许差异的位置:
<R,A> R collect(Collector<? super T,A,R> collector)
? super T
允许差异。
您对 returnsListByContact
、
<T extends Parent> List<T> returnsListByContact(List<T> childList, ...)
不允许差异。它采用 List<T>
和 return 类型的参数 List<T>
。参数和 return 类型必须相同。这就是为什么当您传入 List<Child1>
并尝试从 return 类型为 List<Parent>
的方法 return 时出现不匹配的原因——这些类型不兼容。
要解决此问题,您需要在 returnsListByContact
的声明中添加一些差异。这是我的做法:
<T extends Parent> List<T> returnsListByContact(List<? extends T> childList, ...)
这允许您在传递某些子类型的列表时 return 某种类型的列表,在这种情况下 returning List<Parent>
同时传递 List<Child1>
,这就是我想你想要的。