是什么款式的区别 和收藏 (What is the difference between Co

2019-06-24 21:07发布

我主要是C#开发人员,我在教学中的数据结构来我的朋友,他们在大学中使用Java和我在Java中看到了这样的表达式:

void printCollection(Collection<?> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

我还没有看到在C#这样的事情,所以我不知道有什么之间的区别Collection<T>Collection<?>在Java中?

void printCollection(Collection<T> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}

我认为这可能已经写在上面太的方式。 文档中的人物进行比较Collection<Object>Collection<T>虽然。

实例取自http://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

Answer 1:

Collection<?>是未知的类型参数的集合。

至于来电者而言,有什么区别

void printCollection(Collection<?> c) { ... }

<T> void printCollection(Collection<T> c) { ... }

然而,后者允许执行指集合的类型参数,并且因此通常是优选的。

前者存在语法错误,因为它并不总是能够在适当的范围内引入类型参数。 例如,考虑:

List<Set<?>> sets = new ArrayList<>();
sets.add(new HashSet<String>());
sets.add(new HashSet<Integer>());

如果我要更换? 通过某种类型的参数T ,在所有套sets会被限制在相同的分量类型,即,I可以不再具有不同元件类型分为同一列表把套,就证明了以下的尝试:

class C<T extends String> {
    List<Set<T>> sets = new ArrayList<>();

    public C() {
        sets.add(new HashSet<String>()); // does not compile
        sets.add(new HashSet<Integer>()); // does not compile
    }
}


Answer 2:

声明Collection<?> (读作“未知集合”)是一个集合,其元素类型匹配任何东西,而Collection<T>表示类型的集合T

像往常一样安格莉卡朗格的仿制药FAQ对议题进行了广泛讨论,一个必须读充分了解所有关于Java泛型,特别是无界的通配符(这个问题的主题)。 从FAQ报价:

无界通配符看起来像“?”,并表示该系列的所有类型。 无界通配符用作论据泛型类型的实例。 不需要有关参数化类型的类型参数的知识,其中无界通配符情况下非常有用

欲了解更多技术细节,检查出部分§4.5.1类型参数和通配符的的Java语言规范 ,其中规定:

类型参数可以是参考类型或通配符。 通配符是在需要大约只有类型参数部分知识非常有用。



Answer 3:

随着Collection<T>你可以这样做

void printCollection(Collection<T> c) {
    for (T e : c) {
        System.out.println(e);
    }
}

随着Collection<?>你只知道集合包含的对象。



Answer 4:

(?)的一个使用无界通配符实际上是指? extends Object ? extends Object (任何扩展对象)。

这在Java中,意味着一个只读特性,即,我们被允许从通用结构看项目,但我们不能把任何东西在里面,因为我们不能确定实际类型元素的它。

因此,我敢说它是在一个非常有效的方法printCollection正在讨论的方法,至少,直到我们满足,我们需要假设一种类型的情况。

如果让他们两者之间进行选择,我会说,第二个(与类型参数T)是一个更简洁的方法,因为你至少可以假设集合有某种类型的T ,并能证明是在某些情况下非常有用。

例如,如果需要,收集要同步,我可以简单地这样做:

<T> void printCollection(Collection<T> c) {
    List<T> copy = new ArrayList<T>();
    synchronized(c) {
        copy.addAll(c);
    }
    for (T e : copy) {
        System.out.println(e);
    }
}

我很轻松地创建类型的新的集合T ,和原来的集合的所有元素复制到这个第二个。 这我能做到,因为我可以假设集合的类型是T ,而不是?

我当然可以,跟第一种方法(使用通配符ubounded)同样的事情,但它不是那么干净,我不得不作出假设集合的类型为对象,而不是? (其不能被有效地用作类型参数: new ArrayList<?>()

void printCollection(Collection<?> c) {
    List<Object> copy = new ArrayList<Object>();
    synchronized(c) {
        copy.addAll(c);
    }
    for (Object e : copy) {
        System.out.println(e);
    }
}


文章来源: What is the difference between Collection and Collection