考虑您拥有此列表:
private final List<? extends AbstractXmlElement> inMemoryElements;
包含一堆AbstractXmlElement子类的对象,您想添加一个方法从该列表中过滤特定子类的对象。为此,我创建了以下方法:
public <E extends AbstractXmlElement> List<E> getInstancesOf(Class<E> c) {
return getUsableElements().stream()
.filter(c::isInstance)
.map(e -> (E) e)
.collect(Collectors.toList());
}
然而(E)e导致出现UncheckedCast警告。我想知道这是未经检查的强制转换的确切方式,并且是否可以安全地禁止显示此警告,因为那些不是E实例的对象在强制转换之前已被滤除。依我所知,这个转换永远不会失败
答案 0 :(得分:2)
这到底是未经检查的演员
您唯一的保证是e
是AbstractXmlElement
的实例。但这可以是任何子类。因此,如果您有一个子类A
和B
都扩展了AbstractXmlElement
,则从理论上讲类型约束意味着您可以尝试将A
强制转换为B
,这将失败,如果您将B.class
作为参数传递,并且您的集合包含A
的实例。因此,警告。
请注意,编译器不会检查过滤器表达式以找出只有E
的实例才能使它通过过滤器。特别是,它不会去阅读文档,而是假定文档是正确的。据它所知,c::isInstance()
只是另一个随机方法,它使用Object
并返回boolean
。此时,没有任何迹象表明只有E
的实例保留在过滤器之后的流中。
如果可以安全地禁止显示此警告
在这种情况下,是的。
答案 1 :(得分:2)
这是未经检查的强制类型转换,因为E
的类型为unknown at runtime。由于您正在检查isInstance()
,因此您的代码是安全的。但是,如果要避免警告,可以使用c
进行强制转换:
.map(c::cast)