Java generics Enum subtyping Interface

Given the following setting:

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 doesn't the compiler accept the list as a parameter to accept ()?

List extends Iterable through Collection , so this is not a problem.

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>

But constants are MyInterface ... aren't they?

+5
source share
3 answers

The problem is how Generics work. In particular, Generics are not overridden ... which means that the compiler will not see Iterable<enum.Constants> as Iterable<enum.MyInterface> , even if Constants is a subclass of MyInterface.

However, there is a way around this: General wildcards .

If you change static void accept(Iterable<MyInterface> values) to static void accept(Iterable<? extends MyInterface> values) , it should work.

+4
source

Do you need to use Iterable<? extends MyInterface> Iterable<? extends MyInterface> instead of Iterable<MyInterface> , because although Constants is a subtype of MyInterface , Iterable<Constants> not a subtype of Iterable<MyInterface> - and I will show you why:

If this were the case (it is acceptable to use List instead of Iterable for the following example), I could do this:

 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. 
+2
source

Generic types do not inherit this path, although at first glance this may seem intuitive. Using Iterable<? extends MyInterface> Iterable<? extends MyInterface> allows you to use any Iterable (e.g. a List ) type that extends MyInterface (e.g. Constants ).

0
source

Source: https://habr.com/ru/post/1242879/


All Articles