这是我的代码:
Set<Class<Event>> s = new HashSet<>();
Set<Class<? extends Event>> s2 = new HashSet<>();
Event e = new Event();
s.add(e.getClass()); // #1
s2.add(e.getClass()); // #2
class Event {
// ...
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器会在语句中引发错误#1?
我正在使用Java 7.
如果你看看方法的文档,getClass()你会看到
实际结果类型是
Class<? extends |X|>| X | 是调用getClass的表达式的静态类型的擦除.例如,此代码片段中不需要强制转换:Run Code Online (Sandbox Code Playgroud)Number n = 0; Class<? extends Number> c = n.getClass();
因此,结果e.getClass()将Class<? extends Event>恰好Set<Class<? extends Event>> s2是存储的假设.这就是为什么
s2.add(e.getClass()); // OK
Run Code Online (Sandbox Code Playgroud)
工作良好.
但是如果情况Set<Class<Event>> s有所不同.它只能存储Class<Event>.允许它从Class<? extends Event>引用中存储对象在类型安全性方面是非常危险的.
看看这个例子(为了便于理解,可以替换Class使用List,我们的Action情况会Animal就像Dog和Cat).
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> generalList = dogs;
Set<List<Animal>> set = new HashSet<>();
Run Code Online (Sandbox Code Playgroud)
现在让我们假设Set<List<Animal>> set可以存储List<? extends Animal>
set.add(generalList);
Run Code Online (Sandbox Code Playgroud)
现在我们可以做一些可怕的事了
for (List<Animal> animalList : set){
animalList.add(new Cat()); // I just placed Cat in container full of Dogs!
}
Run Code Online (Sandbox Code Playgroud)
记住我们的List<Dog> dogs = new ArrayList<>();清单?现在它包含Cat如果我这样做:
for (Dog dog : dogs){
dog.speak();
}
Run Code Online (Sandbox Code Playgroud)
我可能会看到类似的东西
wof
woof
Woof
Meow!(psst:让我离开这里!)
......
或者代替Meow!一些例外NoSuchMethodException或者很可能的例外ClassCastException: Cat cannot be cast to Dog.
所以当你看到允许这种机制不是很明智.
| 归档时间: |
|
| 查看次数: |
475 次 |
| 最近记录: |