如何执行以下操作(此操作无法编译):
<T> List<T> getElementsOf() {
return list.stream()
.filter(x -> x instanceof T)
.map(x -> (T) x)
.collect(toList());
}
用法的例子是什么?理想情况下,它应该像obj.<Derived>getElementsOf()
。
答案 0 :(得分:10)
虽然另一个答案几乎完成了这项工作,但这里更好:
<T> List<T> getElementsOf(Class<T> clazz) {
return list.stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.collect(toList());
}
请注意clazz::isInstance
件事。它使用isInstance
方法,而不是比较两个类。根据文档,这相当于instanceof
,这是你想要的第一个。
此方法是Java语言instanceof运算符的动态等价物。
答案 1 :(得分:1)
我得到了以下内容:
<T> List<T> getChildrenOf(Class<T> clazz) {
return children.stream()
.filter(node -> node.getClass() == clazz)
.map(node -> clazz.<T>cast(node))
.collect(toList());
}
List<Mesh> nameNodes = b.getChildrenOf(Mesh.class);
答案 2 :(得分:0)
请注意,泛型类型信息会在运行时被删除,因此为了更清楚,我将T
与Object
进行了交换。实际上Object
也不会存在,但我保持它更清晰,T
所在的地方:
List<Object> getElementsOf() {
return list.stream()
.filter(x -> x instanceof Object) // this is legal, as Object is an actual type, T isn't
.map(x -> (Object) x)
.collect(toList());
}
正如您现在所看到的,这没有多大意义。如果不将其作为参数传递,则无法推断出类型。您已经自己获得了解决方案,我只想让那些不熟悉泛型的人更清楚。
<T> List<T> getElementsOf(Class<T> type) {
return list.stream()
.filter(type::isInstance)
.map(type::cast)
.collect(toList());
}
如果我们现在用Object交换T
,我们会看到类型仍在这里,所以你可以适当地投射它:
List getElementsOf(Class type) {
return list.stream()
.filter(type::isInstance) // is type an Object? is it Long? we don't mind... we passed it and we deliver it
.map(type::cast) // actually this isn't really needed, if you have a return type of List (as you already filtered for the types you want)
.collect(toList());
}
另请注意,使用该方法,在提供类型时,您永远不会获得null
值。在这种情况下,isInstance
将返回false
。