Reputation: 2514
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?
Upvotes: 5
Views: 344
Reputation: 1931
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.
Upvotes: 1
Reputation: 147164
Usual:
class Bar {}
class Baz {}
FooMaker<?> maker = new FooMaker<Bar>();
List<Foo<?>> fooList = maker.getFoos("bar"); //error here!
fooList.add(new Foo<Baz>()); //cock-up here!
Upvotes: 1
Reputation: 140051
Because you are declaring maker
as FooMaker<?>
. Why wouldn't you declare it as the type of AwesomeFooMaker
if you know what specific T
AwesomeFooMaker
returns?
Upvotes: 0