Here is an example of some code I'm working on:
public interface FooMaker<T extends Enum<T> & FooType>
{
public List<Foo<T>> getFoos(String bar);
}
Let's further assume there will be many different concrete implementations of FooMaker. So I wrote some code to utilize the FooMakers.
FooMaker<?> maker = Foos.getRandomMaker();
List<Foo<?>> fooList = maker.getFoos("bar"); //error here!
The second line of code causes the issue, eclipse tells me the code should be:
FooMaker<?> maker = Foos.getRandomMaker();
List<?> fooList = maker.getFoos("bar");
I'm having trouble understanding why the Foo declaration as the parameterized type in List has to go away to make the return type correct.
Any ideas?
Try this instead:
List<? extends Foo<? extends Enum<?>>> fooList = maker.getFoos("bar");
The problem is that if this has been allowed:
List<Foo<?>> fooList = maker.getFoos("bar");
Then by extension, you would've been able to get away with this as well:
Foo<?> foo1 = new Foo<String>();
Foo<?> foo2 = new Foo<Integer>();
fooList.add(foo1);
fooList.add(foo2);
Which would invalidate the generic contract of the returned list.
To prevent this, the java compiler forces the return type to be wildcard-based, meaning Foo can be used as a return-type (to pull elements out of the list) but you will not be able to add wildcard-based Foo types to your list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With