未经检查的 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
和:
MyObjectA
扩展 MyObject
MyListObject
只是实现接口 Collection<O>
和 List<O>
我现在的问题是,下面的代码
MyList<MyObjectA> var = (MyList<MyObjectA>)doSomething();
产生一个
Type safety: Unchecked cast from MyInterface to MyList<MyObjectA>
警告。
为什么?我的意思是 doOperation()
returns 一个 MyInterface
类型并且 MyList
实现了所述接口...
我希望我的代码示例解释了所有 类 和接口之间的完整关系,并且我没有遗漏任何内容。
你假装 MyInterface
是 MyList<>
但我很确定它不是——尽管你没有显示 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 中的保留关键字。您应该避免将其用作变量名。
我的情况是,我有一个函数
public static MyInterface doSomething() {...}
和一个Class
MyList<O extends MyObject> extends MyListObject<O> implements MyInterface
和:
MyObjectA
扩展MyObject
MyListObject
只是实现接口Collection<O>
和List<O>
我现在的问题是,下面的代码
MyList<MyObjectA> var = (MyList<MyObjectA>)doSomething();
产生一个
Type safety: Unchecked cast from MyInterface to MyList<MyObjectA>
警告。
为什么?我的意思是 doOperation()
returns 一个 MyInterface
类型并且 MyList
实现了所述接口...
我希望我的代码示例解释了所有 类 和接口之间的完整关系,并且我没有遗漏任何内容。
你假装 MyInterface
是 MyList<>
但我很确定它不是——尽管你没有显示 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 中的保留关键字。您应该避免将其用作变量名。