上限有限的通配符,迭代器和for-each循环

时间:2014-12-05 10:04:08

标签: java generics casting

我不明白为什么这段代码会编译:

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循环一起工作?

2 个答案:

答案 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变量中的存储仅针对与其相关的每个元素进行。