为什么Java编译器触发&#34;未经检查的强制转换&#34;将Class<? extends Object>
投射到Class<Object>
时发出警告?这个演员怎么可能失败?
答案 0 :(得分:3)
这样的强制转换在一般情况下根本不安全,并且无法检测到Class
类安全的事实。想象一下这样的课程:
// Hypothetical!
class MyClass<T> extends Class<T> {
public T someInstance;
}
现在,如果允许使用相关广播,您可以执行类似
的操作MyClass<Integer> myClassWithInteger = new MyClass<Integer>();
myClassWithInteger.someInstance = someInteger;
// This is valid
MyClass<? extends Object> myClassWithWildcard = myClassWithInteger;
// This is NOT valid, but let's assume it was:
MyClass<Object> myClassWithObject = myClassWithWildcard;
// This would be valid, because 'someInstance' was of type 'Object' here
myClassWithObject.someInstance = "someString";
// This is valid. But through the unchecked cast, we silently
// sneaked in an STRING as this instance. So this would fail:
Integer i = myClassWithInteger.someInstance;
你在评论中提到:
你是说语言作者想要避免对像Class这样的安全课程进行特殊处理,所以他们全面禁止这样做吗?
是。关键点在于这样一个演员是否安全的问题取决于该类的语义。 语法无法检测到安全性。
答案 1 :(得分:0)
这确实不会失败。但这是一个上传的一般警告,无论其参数如何。
你可以改用:
Class<? extends Object> clazz = String.class;
Class<?> clazzObject = clazz; // Does not generate Warning.
答案 2 :(得分:0)
如果您不想通过使用泛型确保特定类别的界面,您应该使用&#34;?&#34;而不是&#34;? extends Object&#34;。编译器在编译时为每个无界泛型参数假定Object。
答案 3 :(得分:0)
这并不是说它是非法的,它说它不安全并且可能导致运行时错误。
请考虑以下代码:
List<Integer> li = new ArrayList<Integer>();
List<? extends Number> lf = li;
List<Number> ln = (List<Number>)lf;
ln.add(new Float(1.1));
Integer value = li.get(0);
它会在最后一行失败,因为我们通过这种不安全的情况偷偷进入整数列表中的Float。