Java 通用列表<列表<? 扩展数>>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/746089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Generic List<List<? extends Number>>
提问by
How come in java we cannot do:
为什么在java中我们不能这样做:
List<List<? extends Number>> aList = new ArrayList<List<Number>>();
Even though this is OK:
即使这没问题:
List<? extends Number> aList = new ArrayList<Number>();
Compiler error message is:
编译器错误信息是:
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
Type mismatch: cannot convert from ArrayList<List<Number>> to List<List<? extends Number>>
回答by eulerfx
I'm not very familiar with Java syntax but it seems that your issue is this:
我对 Java 语法不是很熟悉,但您的问题似乎是这样的:
回答by Apocalisp
Your statement does not compile because List<? extends Number>
is not the same type as List<Number>
. The former is a supertype of the latter.
您的语句无法编译,因为List<? extends Number>
与List<Number>
. 前者是后者的超类型。
Have you tried this? Here I'm expressing that the List is covariant in its type argument, so it will accept any subtype of List<? extends Number>
(which includes List<Number>
).
你试过这个吗?在这里,我表示 List 在其类型参数中是协变的,因此它将接受List<? extends Number>
(包括List<Number>
) 的任何子类型。
List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();
Or even this. Here the type parameter for the ArrayList on the right-hand side is the same as the type parameter on the left-hand side, so variance is not an issue.
甚至这个。这里右侧 ArrayList 的类型参数与左侧的类型参数相同,因此差异不是问题。
List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
You should be able to just say
你应该可以说
List<List<Number>> aList = new ArrayList<List<Number>>();
I tend to avoid the ?
type wildcard whenever possible. I find that the expense incurred in type annotation is not worth the benefit.
我倾向于尽可能避免使用?
类型通配符。我发现类型注释中产生的费用不值得收益。
回答by Steve Reed
You should definitely use the ? type wildcard when appropriate, do not avoid it as a general rule. For example:
你绝对应该使用 ? 在适当的时候输入通配符,一般情况下不要避免使用通配符。例如:
public void doThingWithList(List<List<? extends Number>> list);
allows you to pass a List<Integer>
or a List<Long>
.
允许您传递 aList<Integer>
或List<Long>
.
public void doThingWithList(List<List<Number>> list);
allows you to only pass arguments declared as List<Number>
. A small distinction, yes, but using the wildcard is powerful and safe. Contrary to how it may seem, a List<Integer>
is not a subclass, or is not assignable, from List<Number>
. Nor is List<Integer>
a subclass of List<? extends Number
, which is why the code above does not compile.
允许您只传递声明为List<Number>
. 一个小小的区别,是的,但使用通配符是强大且安全的。与它看起来的相反, aList<Integer>
不是子类,或者不可分配,来自List<Number>
。也不是List<Integer>
的子类List<? extends Number
,这就是上面的代码无法编译的原因。
回答by John Feminella
In Java, if Car
is a derived class of Vehicle
, then we can treat all Cars
as Vehicles
; a Car
is a Vehicle
. However, a List
of Cars
is not also a List
of Vehicles
. We say that List<Car>
is not covariantwith List<Vehicle>
.
在 Java 中,如果Car
是 的派生类Vehicle
,那么我们可以将所有Cars
视为Vehicles
; 一个Car
是一个Vehicle
。然而,a List
ofCars
也不是 a List
of Vehicles
。我们说List<Car>
的不是协变有List<Vehicle>
。
Java requires you to explicitly tell it when you would like to use covariance and contravariance with wildcards, represented by the ?
token. Take a look at where your problem happens:
Java 要求您明确告诉它何时想要使用通配符表示的协方差和逆变?
。看看你的问题发生在哪里:
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------- ------
//
// "? extends Number" matched by "Number". Success!
The inner List<? extends Number>
works because Number
does indeed extend Number
, so it matches "? extends Number
". So far, so good. What's next?
内部List<? extends Number>
工作因为Number
确实扩展Number
,所以它匹配“ ? extends Number
”。到现在为止还挺好。下一步是什么?
List<List<? extends Number>> l = new ArrayList<List<Number>>();
// ---------------------- ------------
//
// "List<? extends Number>" not matched by "List<Number>". These are
// different types and covariance is not specified with a wildcard.
// Failure.
However, the combined inner type parameter List<? extends Number>
is not matched by List<Number>
; the types must be exactly identical. Another wildcard will tell Java that this combined type should also be covariant:
但是,组合的内部类型参数List<? extends Number>
不匹配List<Number>
; 类型必须完全相同。另一个通配符将告诉 Java 这种组合类型也应该是协变的:
List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();
回答by Alex
List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
aList.add(new ArrayList<Integer>());