[英]Java generics Enum subtyping Interface
Given the following setup: 鉴于以下设置:
public class TestType {
public static void main(String[] args) {
List<Constants> list = new ArrayList<>();
accept(list); //Does not compile
}
static void accept(Iterable<MyInterface> values) {
for (MyInterface value : values) {
value.doStuff();
}
}
}
interface MyInterface<T> {
T doStuff();
}
enum Constants implements MyInterface<Integer> {
ONE, TWO, THREE;
@Override
public Integer doStuff() {
return ordinal();
}
}
Why won't the compiler accept the list as parameter to accept()? 为什么编译器不接受列表作为accept()的参数?
List
extends Iterable
via Collection
so that isn't the problem. List
通过Collection
扩展Iterable
,这不是问题。
On the other hand, the compiler tells me that incompatible types: java.util.List<enums.Constants> cannot be converted to java.lang.Iterable<enums.MyInterface>
另一方面,编译器告诉我incompatible types: java.util.List<enums.Constants> cannot be converted to java.lang.Iterable<enums.MyInterface>
But Constants IS a MyInterface... isn't it? 但常量是一个MyInterface ......不是吗?
The problem is with how Generics work. 问题在于泛型如何工作。 Specifically, Generics are non-reified... meaning that the compiler will not see an Iterable<enum.Constants>
as an Iterable<enum.MyInterface>
even if Constants is a sub-class of MyInterface. 具体来说,泛型是非规范的......这意味着即使Constants是MyInterface的子类,编译器也不会将Iterable<enum.Constants>
看作Iterable<enum.MyInterface>
。
However, there is a way to get around it: Generic wildcards . 但是,有一种方法可以解决它: 通用通配符 。
If you change static void accept(Iterable<MyInterface> values)
to static void accept(Iterable<? extends MyInterface> values)
, it should work. 如果将static void accept(Iterable<MyInterface> values)
更改为static void accept(Iterable<? extends MyInterface> values)
,它应该可以工作。
You need to use Iterable<? extends MyInterface>
你需要使用Iterable<? extends MyInterface>
Iterable<? extends MyInterface>
instead of Iterable<MyInterface>
because even though Constants
is a subtype of MyInterface
, Iterable<Constants>
is not a subtype of Iterable<MyInterface>
- and I'll show you why: Iterable<? extends MyInterface>
而不是Iterable<MyInterface>
因为即使Constants
是MyInterface
的子类型, Iterable<Constants>
也不是Iterable<MyInterface>
的子Iterable<MyInterface>
- 我将向您展示原因:
If it was so (let's use List
instead of Iterable
for the next example), I would be able to do this: 如果是这样(让我们使用List
而不是Iterable
用于下一个例子),我将能够这样做:
List<Constant> constantsList = new ArrayList<Constants>(); // list of constants
List<MyInterface> ifaceList = constantsList; // you said this would be OK ...
// assume MyOtherImplementation is another implmentation of MyInterface
ifaceList.add(new MyOtherImplementation()); // OK, MyOtherImplementation implements MyInterface
Constant myConst = constantsList.get(0); // Oops! I just got an instance of MyOtherImplementation from List<Constant> - not cool.
Generic types do not inherit this way, although it may seem counter-intuitive at first glance. 通用类型不会以这种方式继承,尽管乍一看似乎是违反直觉的。 Using Iterable<? extends MyInterface>
使用Iterable<? extends MyInterface>
Iterable<? extends MyInterface>
will allow you to use any Iterable
(eg, a List
) of a type that extends MyInterface
(eg Constants
). Iterable<? extends MyInterface>
将允许你使用任何Iterable
(例如,一个List
扩展的类型) MyInterface
(如Constants
)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.