2016-02-12 2 views
5

Учитывая следующие настройки:Java дженериков Enum подтипов Интерфейс

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

Проблема в том, как работают Generics. В частности, Generics не подтверждены ... что означает, что компилятор не увидит Iterable<enum.Constants> как Iterable<enum.MyInterface>, даже если Constants является подклассом MyInterface.

Однако есть возможность обойти его: Generic wildcards.

Если вы меняете static void accept(Iterable<MyInterface> values) на static void accept(Iterable<? extends MyInterface> values), это должно работы.

+0

Это действительно работает. Примите ответ, как только SO дайте мне. Большое спасибо! – tannerli

0

Общие типы не наследуют этот путь, хотя на первый взгляд это может показаться встречным интуитивным. Использование Iterable<? extends MyInterface> позволит вам использовать любые Iterable (например, a List) типа, который расширяет MyInterface (например, Constants).

2

Вы должны использовать Iterable<? extends MyInterface> вместо Iterable<MyInterface>, потому что даже Constants является подтипом MyInterface, 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. 
Смежные вопросы