Java未经检查的强制转换为类型参数警告,尽管是

时间:2018-07-30 19:06:35

标签: java type-parameter unchecked-cast

考虑您拥有此列表:

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实例的对象在强制转换之前已被滤除。依我所知,这个转换永远不会失败

2 个答案:

答案 0 :(得分:2)

  

这到底是未经检查的演员

您唯一的保证是eAbstractXmlElement的实例。但这可以是任何子类。因此,如果您有一个子类AB都扩展了AbstractXmlElement,则从理论上讲类型约束意味着您可以尝试将A强制转换为B,这将失败,如果您将B.class作为参数传递,并且您的集合包含A的实例。因此,警告。

请注意,编译器不会检查过滤器表达式以找出只有E的实例才能使它通过过滤器。特别是,它不会去阅读文档,而是假定文档是正确的。据它所知,c::isInstance()只是另一个随机方法,它使用Object并返回boolean。此时,没有任何迹象表明只有E的实例保留在过滤器之后的流中。

  

如果可以安全地禁止显示此警告

在这种情况下,是的。

答案 1 :(得分:2)

这是未经检查的强制类型转换,因为E的类型为unknown at runtime。由于您正在检查isInstance(),因此您的代码是安全的。但是,如果要避免警告,可以使用c进行强制转换:

.map(c::cast)