我主要是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
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
}
}
声明Collection<?>
(读作“未知集合”)是一个集合,其元素类型匹配任何东西,而Collection<T>
表示类型的集合T
。
像往常一样安格莉卡朗格的仿制药FAQ对议题进行了广泛讨论,一个必须读充分了解所有关于Java泛型,特别是无界的通配符(这个问题的主题)。 从FAQ报价:
无界通配符看起来像“?”,并表示该系列的所有类型。 无界通配符用作论据泛型类型的实例。 不需要有关参数化类型的类型参数的知识,其中无界通配符情况下非常有用
欲了解更多技术细节,检查出部分§4.5.1类型参数和通配符的的Java语言规范 ,其中规定:
类型参数可以是参考类型或通配符。 通配符是在需要大约只有类型参数部分知识非常有用。
随着Collection<T>
你可以这样做
void printCollection(Collection<T> c) {
for (T e : c) {
System.out.println(e);
}
}
随着Collection<?>
你只知道集合包含的对象。
(?)的一个使用无界通配符实际上是指? 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);
}
}