未经检查的 Cast 警告:接口作为 return 值,存储在实现所述接口的 Class 中

Unchecked Cast Warning: interface as return value, stored in Class implementing said interface

我的情况是,我有一个函数

public static MyInterface doSomething() {...}

和一个Class

MyList<O extends MyObject> extends MyListObject<O> implements MyInterface

和:

我现在的问题是,下面的代码

MyList<MyObjectA> var = (MyList<MyObjectA>)doSomething();

产生一个

Type safety: Unchecked cast from MyInterface to MyList<MyObjectA>

警告。
为什么?我的意思是 doOperation() returns 一个 MyInterface 类型并且 MyList 实现了所述接口...

我希望我的代码示例解释了所有 类 和接口之间的完整关系,并且我没有遗漏任何内容。

你假装 MyInterfaceMyList<> 但我很确定它不是——尽管你没有显示 MyInterface.

的实际定义

打个比方,您正试图将所有工具 (MyInterface) 视为锤子 (MyList<>)。

如果您确定 doSomething() 总是 returns 一个 MyList,您可以使用 @SuppressWarnings("unchecked") 注释标记包含转换的方法。但是,为什么首先要声明 doSomething() 返回更通用的 MyInterface

interface Flying {
   void fly();
}

class Bird extends Animal implements Flying {
    ...
}

List<Flying> listFlying();

List<Flying> list = listFlying();

如果确实只使用接口的方法,可以使用:

list.forEach(flying -> flying.fly());

否则安全需要一些铲子:

List<Bird> birds = list.stream() // Or listFlying().stream()
    .filter(Bird.class::isInstance)
    .map(Bird.class::cast)
    .collect(Collectors.toList());

本质上,强制转换中的类型可能不包含 <…>,除非它是 <?>。 (此规则也有例外,但它们是极端情况,与此处无关。)

泛型是一种编译时类型检查机制。在运行时,由于类型擦除,不存在 MyList<MyObjectA> class。只有一个 MyList class.

这意味着编译器只能生成这段代码:

(MyList<?>) doSomething();

试图强制编译器假定结果具有特定的泛型类型是 不安全的, 因为将执行转换的代码无法对此进行检查。因此,您的演员表是未经检查的演员表。

执行此操作的安全方法是执行非泛型转换:

MyList<MyObjectA> var = new MyList<>();
MyList<?> list = (MyList<?>) doSomething();
for (Object element : list) {
    var.add((MyObjectA) element);
}

注意: var 现在是 Java 中的保留关键字。您应该避免将其用作变量名。