为什么这是一个未经检查的演员表?以及如何解决?
Why is this an unchecked cast? And how to fix it?
我有以下代码:
public final <T extends Component> T getComponent(Class<T> type) {
Iterator<Component> it = components.iterator();
while(it.hasNext()) {
Component next = it.next();
if(type.isAssignableFrom(next.getClass()))
return (T)next; // Why is this an unchecked cast from Component to T?
}
return null;
}
并且出于某种原因,return (T)next;
是从 Component 到 T 的未经检查的转换。
我不确定这是为什么,因为 T 必须扩展 Component,它应该能够安全地将它转换为 Component 的任何子类,对吗?
如果我手动执行 return (TestComponent)next;
并将 return 类型更改为 TestComponent 它工作正常,那么为什么它不能与 T 一起工作?
由于T是Component的子类,所以每个T都是一个Component,但不是每个Component都是T。
如果子类继承自超类,则无法成功将超类转换为子类。
因此无法将新组件转换为 T 实例。
其他人已经描述了问题,这里是解决方案(使用更清洁的测试):
if(type.isInstance(next) {
return type.cast(next);
}
这是一个未经检查的转换,因为编译器无法确定 next
是 T
。它只知道它是一个 Component
.
至于为什么转换为 T
会生成警告,而不是转换为 TestComponent
,这个问题要微妙得多。投射到 TestComponent
本质上比投射到 T
更狡猾。如果 test
不是 TestComponent
,转换为 TestComponent
将在运行时导致 ClassCastException
。但这不是转换为 T
的情况,因为由于类型擦除,类型 T
在运行时是未知的。如果您将不是 T
的 Component
转换为 T
,然后将结果添加到 List<T>
,您将得到一个 List<T>
,其中不是全部的项目是 T
s。这将破坏泛型应该提供的保证。 ClassCastException
不可能阻止这种情况。
对于你的情况,你不必担心。通过传递 Class<T>
对象并进行检查,您已经检查到 T
的转换是安全的。你有两个选择。您 可以 取消警告并添加注释解释为什么这样做是安全的。但是,更好的替代方法是改写 return type.cast(next);
。这不会生成警告,因为如果 object
不是 T
,type.cast(object)
会 抛出 ClassCastException
。
我有以下代码:
public final <T extends Component> T getComponent(Class<T> type) {
Iterator<Component> it = components.iterator();
while(it.hasNext()) {
Component next = it.next();
if(type.isAssignableFrom(next.getClass()))
return (T)next; // Why is this an unchecked cast from Component to T?
}
return null;
}
并且出于某种原因,return (T)next;
是从 Component 到 T 的未经检查的转换。
我不确定这是为什么,因为 T 必须扩展 Component,它应该能够安全地将它转换为 Component 的任何子类,对吗?
如果我手动执行 return (TestComponent)next;
并将 return 类型更改为 TestComponent 它工作正常,那么为什么它不能与 T 一起工作?
由于T是Component的子类,所以每个T都是一个Component,但不是每个Component都是T。
如果子类继承自超类,则无法成功将超类转换为子类。
因此无法将新组件转换为 T 实例。
其他人已经描述了问题,这里是解决方案(使用更清洁的测试):
if(type.isInstance(next) {
return type.cast(next);
}
这是一个未经检查的转换,因为编译器无法确定 next
是 T
。它只知道它是一个 Component
.
至于为什么转换为 T
会生成警告,而不是转换为 TestComponent
,这个问题要微妙得多。投射到 TestComponent
本质上比投射到 T
更狡猾。如果 test
不是 TestComponent
,转换为 TestComponent
将在运行时导致 ClassCastException
。但这不是转换为 T
的情况,因为由于类型擦除,类型 T
在运行时是未知的。如果您将不是 T
的 Component
转换为 T
,然后将结果添加到 List<T>
,您将得到一个 List<T>
,其中不是全部的项目是 T
s。这将破坏泛型应该提供的保证。 ClassCastException
不可能阻止这种情况。
对于你的情况,你不必担心。通过传递 Class<T>
对象并进行检查,您已经检查到 T
的转换是安全的。你有两个选择。您 可以 取消警告并添加注释解释为什么这样做是安全的。但是,更好的替代方法是改写 return type.cast(next);
。这不会生成警告,因为如果 object
不是 T
,type.cast(object)
会 抛出 ClassCastException
。