getClass返回什么类型?

时间:2015-04-02 10:36:26

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

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

我正在使用Java 7.

1 个答案:

答案 0 :(得分:9)

如果您查看documentation of getClass() method,您会看到

  

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

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>引用的对象在类型安全性方面非常危险。

请看一下这个示例(为了便于理解,我们可以将Class替换为List,我们的Action个实例将Animal类似Dog和{ {1}})。

Cat

现在我们假设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

我可能会看到类似于

的内容
  

WOF
  纬
  汪
  喵! (psst:让我离开这里!)
  ...

或代替for (Dog dog : dogs){ dog.speak(); } 某些例外,例如Meow!或最有可能NoSuchMethodException

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