getClass返回什么类型?

Ste*_*han 3 java generics

这是我的代码:

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.

Psh*_*emo 9

如果你看看方法的文档,getClass()你会看到

实际结果类型是Class<? extends |X|>| X | 是调用getClass的表达式的静态类型的擦除.例如,此代码片段中不需要强制转换:

Number n = 0; 
Class<? extends Number> c = n.getClass();
Run Code Online (Sandbox Code Playgroud)

因此,结果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就像DogCat).

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.

所以当你看到允许这种机制不是很明智.