为什么向上升级被视为不安全的操作?

时间:2014-04-22 07:02:01

标签: java generics type-safety

为什么Java编译器触发&#34;未经检查的强制转换&#34;将Class<? extends Object>投射到Class<Object>时发出警告?这个演员怎么可能失败?

4 个答案:

答案 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。