Java 为什么这是一个未经检查的演员阵容?如何修复它?
我有以下代码:Java 为什么这是一个未经检查的演员阵容?如何修复它?,java,generics,iterator,Java,Generics,Iterator,我有以下代码: 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.get
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;
}
public final T getComponent(类类型){
迭代器it=components.Iterator();
while(it.hasNext()){
Component next=it.next();
if(键入.isAssignableFrom(next.getClass()))
return(T)next;//为什么这是从组件到T的未检查强制转换?
}
返回null;
}
出于某种原因,return(T)next代码>是从组件到T的未选中强制转换
我不确定这是为什么,因为T必须扩展组件,它应该能够安全地将其转换为组件的任何子类,对吗
如果我手动执行下一步返回(TestComponent)编码>并将返回类型更改为TestComponent它可以正常工作,那么为什么它不能与t一起工作?因为t是组件的子类,每个t都是组件,但不是每个组件都是t
如果子类继承自超类,则无法成功执行将超类强制转换为子类的操作
因此,不能将新组件强制转换为T实例。其他人已经描述了该问题,以下是解决方案(使用cleaner test):
这是未经检查的强制转换,因为编译器无法确定next
是T
。它只知道它是一个组件
至于您的问题,为什么强制转换到T
会生成警告,而不是强制转换到TestComponent
,这要微妙得多。转换为TestComponent
本质上比转换为T
更不可靠。如果test
不是TestComponent
,则转换为TestComponent
将在运行时导致ClassCastException
。但强制转换为t
的情况并非如此,因为由于类型擦除,类型t
在运行时是未知的。如果您将一个非T
的组件
强制转换为T
,然后将结果添加到列表
,您将拥有一个列表
,其中并非所有项目都是T
s。这将打破仿制药应该提供的保证。不会有ClassCastException
阻止这种情况发生
就你而言,你不必担心。通过传递类
对象并进行检查,您已经检查了对T
的强制转换是否安全。你有两个选择。您可以抑制警告并添加注释,解释为什么这样做是安全的。然而,更好的选择是编写返回类型.cast(下一步)代码>取而代之。这不会生成警告,因为如果object
不是t
,则type.cast(object)
将抛出ClassCastException
然而,在我的例子中,我看到行if(type.isAssignableFrom(next.getClass()){
确保next
是T
类型,对吗?是isAssignableFrom()
检查类型是否相同,或者是next.getClass()的超类/超接口
。因此,如果T
与组件
的类型相同,这将返回true,但您仍然无法将组件
强制转换为T
实例,因为并非每个组件
都将是T
实例,因此编译器不允许使用它。我明白了,所以从技术上讲,它确实检查了实例xt
是T
的一个实例,但编译器不知道这一点,因此发出了警告。是的,很抱歉,我在上面的评论中被搞混了。它检查next
是否是T
的一个实例/超类/超接口,而不是像我在上面的评论中所说的那样。也就是说,它检查参数是否传入IsAssignableFrom()
是调用isAssignableFrom()
所引用的对象的实例/超类/超接口。使用@SuppressWarnings是不正确的,原因与执行“捕获(异常)”是不正确的。“我确定我没有犯错误”这不是一个很好的理由;人们确实会犯错误,方法会在以后被修改。@VGR这是胡说八道。如果你能证明某些东西是安全的,那么完全可以取消警告并添加注释来解释为什么可以。这是Josh Bloch在有效Java中的建议。@pbabcdefp是正确的。取消警告也可以当您完全确定代码不会导致问题时,例如运行时异常。请确保对警告的抑制覆盖了尽可能小的范围。@DermotBlair实际上我认为我只正确了一半。如果您真的没有其他选择,则可以抑制警告,只要您能证明它是安全的。但在这种情况下,y您确实可以选择编写返回类型.cast(下一步);
作为已接受的答案。是的,我同意,当您有选择时,不应使用它。在本例中,绝对不应使用它。仅当您需要消除编译器警告时(例如,公司政策)才应使用它你肯定知道代码是安全的,但是@VGR说“使用@SuppressWarnings永远都不正确”,我认为这有点不正确。
if(type.isInstance(next) {
return type.cast(next);
}