如果new ArrayList <Set<?>>() - 为什么它可以?
new ArrayList<?>(); // is not Legal
如果
new ArrayList<? extends Number>(); // is not Legal,
那么为什么
new ArrayList<Set<?>>(); // IS Legal
有人可以用例子来解释。
如果new ArrayList <Set<?>>() - 为什么它可以?
new ArrayList<?>(); // is not Legal
如果
new ArrayList<? extends Number>(); // is not Legal,
那么为什么
new ArrayList<Set<?>>(); // IS Legal
有人可以用例子来解释。
发生这种情况是因为在您的具体类型声明中,您将接口用作泛型参数。想想如何在将来使用:
List someList = new ArrayList<Set<?>>();
Set<?> someSet = new HashSet<Integer>();
someList.add(someSet);
在第一线 - 你定义ArrayList
类型的列表,将举行“一些集”(任何类型)。然后,在第二行中,您声明并定义了一组具体类型HashSet
。它被铸造成Set<?>
,所以将它添加到先前创建的列表中没有问题。
创建ArrayList时,您必须为其泛型参数指定显式类型。 ?
或? extends Number
不是类型。 Set<?>
是一种类型(即Set,我们不关心它的泛型类型)。
这是因为未知?
无法翻译成任何类型。
new ArrayList<?>();
将导致以下情况(假设可以编译)。
List<?> list = new ArrayList<?>();
list.add(? e); //Java sees this as WTF???
由于这?
是未知的,Java的转换这list.add(null e);
,这是errornous。
的答案已经给出了,所以这里就是你需要做的什么,而不是:
ArrayList example1 = new ArrayList(); // any object will do.
ArrayList<Object> example2 = new ArrayList<Object>(); // since everything inherits from Object anyway...
:
的,如果你不关心的事情的清单中包含的类型是什么第一
然后,如果你想添加任意Number
对象是什么:
ArrayList<Number> example3 = new ArrayList<Number>(); // any Number may be added
最后,以前的答案格罗斯你的最后一个例子的意义。
ArrayList<Set<?>> example4 = new ArrayList<Set<?>>();
这一个意味着你构建你希望找到一个ArrayList
/放Set
S的可以包含任意类型的对象。即你不在乎Set
中的内容,但是你确实在乎它是Set
是你添加到你的ArrayList
。
结果,你的新声明的执行的所有操作的范围内/创建ArrayList
的Set<?>
的部分可以自由地转换为Set
:结果程序将有相当的语义。
new ArrayList<?>()
不会很有用。这是有帮助的想想通配符的意思是:
? extends Foo
意味着你不能把任何东西(除了null
),但你可以得到的物品运为Foo
? super Foo
意味着你可以把Foo
S IN,但你不能让物体出(除Object
)?
是交集:你不能把任何东西(除了null
),并且你不能出去的对象(除Object
)请注意,List<Foo>
可以投射到List<? extends Foo>
,List<? super Foo>
或List<?>
,但这三者中的任何一个都不能安全投射到List<Foo>
。
因此,假设您创建了new ArrayList<?>()
。你可以给它分配什么样的参考?只有一个List<?>
。这意味着你将无法将任何引用放入(除null之外),并且除了Object
之外,您将无法获取任何引用。换句话说,这个泛型比泛型替代的原始类型略有用处。
当您看到List<?>
或List<? extends Foo>
时,很有可能有人将其创建为非通配类型,然后将其转换为通配类型。例如:
List<? extends Number> getSomeNumbers() {
List<Number> numbers = new ArrayList<Number>();
numbers.add(1);
numbers.add(2L);
numbers.add(3.14);
return numbers; // implicit casting to List<? extends Number>
}
在这个例子中,如果numbers
一直类型为List<? extends Number>
,没有add
行会编译,所以它不会是有益的。如果我们将对象构建为new ArrayList<? extends Number>()
,我们别无选择,只能以无用的通配形式引用它。
同样,如果您创建了new ArrayList<? super Number>()
,那么这些添加就可以工作,但是您应该保证没有人能够检索到值,除非是Object
。你可以通过创建(和引用)new ArrayList<Object>()
来做同样的事情。
那么,为什么new ArrayList<Set<?>>()
允许?因为它是有用;我们可以添加元素到列表中,以及检索它们。当我们创建每个集合时,我们将创建它,而不使用通配符,以便我们可以添加它,然后我们将它放下并添加到列表中。
List<Set<?>> getSomeSets() {
List<Set<?>> list = new ArrayList<Set<?>>();
Set<Number> set = new HashSet<Number>();
set.add(1);
set.add(2L);
set.add(3.14);
Set<?> wildcardSet = set; // allowed, though not actually needed
list.add(wildcardSet);
list.add(set); // don't need to go through intermediate wildcardSet
return list;
}
如果这是真的,'名单>名单=新的ArrayList
@yshavit,我没有指定'ArrayList
我明白了,但如果你用'List > list = new ArrayList