2016-02-12 170 views
5

鉴于以下设置:Java泛型枚举子类型接口

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(); 
    } 
} 

为什么不编译器接受列表作为参数来接受()?

List延伸Iterable通过Collection所以这不是问题。

在另一方面,编译器告诉我, incompatible types: java.util.List<enums.Constants> cannot be converted to java.lang.Iterable<enums.MyInterface>

但常量是一个MyInterface的......不是吗?

回答

4

问题在于泛型如何工作。具体而言,泛型没有具体化......这意味着即使Constants是MyInterface的子类,编译器也不会将Iterable<enum.Constants>看作Iterable<enum.MyInterface>

但是,有一种方法可以避开它:Generic wildcards

如果将static void accept(Iterable<MyInterface> values)更改为static void accept(Iterable<? extends MyInterface> values),则其应该的工作。

+0

这确实有效。只要让我来接受答案。非常感谢! – tannerli

0

泛型类型不会继承这种方式,尽管它乍看起来可能看起来不符合直觉。使用Iterable<? extends MyInterface>将允许您使用延伸MyInterface(例如Constants)类型的任何Iterable(例如List)。

2

您需要使用Iterable<? extends MyInterface>,而不是Iterable<MyInterface>,因为即使ConstantsMyInterface一个亚型,Iterable<Constants>不是Iterable<MyInterface>亚型 - 我会告诉你为什么:

如果是这样(让我们用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.