我不明白为什么这段代码会编译:
public void test(Collection<? extends Enum> enumCollection) {
for (Enum e : enumCollection) {
}
}
而这个没有:
public void test(Collection<? extends Enum> enumCollection) {
Iterator<Enum> iterator = enumCollection.iterator();
//Required: Iterator<Java.lang.Enum>
//Found: Iterator<capture<? extends Java.lang.Enum>>
}
在所有情况下, ? extends Enum
应该是Enum
的子类型,那么为什么我会在迭代器中遇到编译错误?为什么它与for-each循环一起工作?
答案 0 :(得分:7)
如果你需要使用,我经常会发现格言?在您的通用中,您可能做错了。
这很好用:
public <T extends Enum> void test(Collection<T> enumCollection) {
for (Enum e : enumCollection) {
}
Iterator<T> iterator = enumCollection.iterator();
}
您的问题是,您希望泛型行为像普通代码一样ArrayList
也是List
。它不是为此而设计的。泛型是为了确保您使用相同的类型,而不是只使用某些兼容类型。
在您的情况下 - 要匹配您可以使用的? extends Enum
:
Iterator<?> iterator = enumCollection.iterator();
工作正常。
你的类型不匹配 - 并且确保他们这样做的是泛型。
请记住,?
并不意味着我不关心它是什么类型它意味着我不想知道它是什么类型< / em>的。在泛型类型中使用?
然后期望能够使用该类型只是愚蠢。
答案 1 :(得分:2)
关于for循环,根据JLS 14.14.2,以下代码:
public void test(Collection<? extends Enum> enumCollection) {
for (Enum e : enumCollection) {
}
}
将被翻译成这样的东西:
public <T extends Enum> void test(Collection<T> enumCollection) {
for (Iterator<T> iterator = enumCollection.iterator(); iterator.hasNext();) {
Enum e = (T) iterator.next();
}
}
哪个编译没有问题。正如您所看到的,您永远不会直接拥有Iterator<Enum>
,而是您所说的任何内容的Iterator
都是您收藏中元素的类型。
JLS的相关部分是:
如果Expression的类型是某个类型参数X的Iterable的子类型,那么让我成为java.util.Iterator类型;否则,让我成为原始类型java.util.Iterator。
Enum
变量中的存储仅针对与其相关的每个元素进行。