getClass return 是什么类型?

What type does getClass return?

这是我的代码:

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 {
    // ...
}

为什么编译器会在语句 #1 上引发错误?

我正在使用 Java 7.

如果你看一下 documentation of getClass() method 你会看到

The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. For example, no cast is required in this code fragment:

Number n = 0; 
Class<? extends Number> c = n.getClass();

所以 e.getClass() 的结果将是 Class<? extends Event>,这正是 Set<Class<? extends Event>> s2 应该存储的内容。这就是为什么

s2.add(e.getClass());   // OK 

工作正常。


但在 Set<Class<Event>> s 的情况下,情况略有不同。它只能存储 Class<Event>。允许它存储来自 Class<? extends Event> 引用的对象在类型安全方面是非常危险的。

看看这个例子(为了更容易理解,让我们用 List 替换 Class 并且我们的 Action 实例将是 Animal 就像 DogCat).

List<Dog> dogs = new ArrayList<>(); 
List<? extends Animal> generalList = dogs;

Set<List<Animal>> set = new HashSet<>();

现在假设 Set<List<Animal>> set 可以存储 List<? extends Animal>

set.add(generalList);

现在我们可以做一些可怕的事情了

for (List<Animal> animalList : set){
    animalList.add(new Cat()); // I just placed Cat in container full of Dogs!
}

还记得我们的 List<Dog> dogs = new ArrayList<>(); 列表吗?现在它包含 Cat 所以如果我这样做:

for (Dog dog : dogs){
    dog.speak();
}

我可能会看到类似于

的内容

wof
woof
Woof
Meow! (psst: Get me out of here!)
...

或者代替 Meow! 一些异常,比如 NoSuchMethodException 或者很可能是 ClassCastException: Cat cannot be cast to Dog.

因此,如您所见,允许这种机制并不是很明智。