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
就像 Dog
和 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
所以如果我这样做:
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
.
因此,如您所见,允许这种机制并不是很明智。
这是我的代码:
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
就像 Dog
和 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
所以如果我这样做:
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
.
因此,如您所见,允许这种机制并不是很明智。