Rocky Pulley
Rocky Pulley

Reputation: 23301

Generic method not properly recognizing type

I have a class that has a member defined as:

Map<Class<? extends Model>, List<? extends Model>> mockStore;

In this class I have a method:

protected <T extends Model> void insertMockStore(T obj)
{
    mockStore.get(obj.getClass()).add(obj);
}

But this method gives a compilation error:

The method add(capture#8-of ? extends Model) in the type List is not applicable for the arguments (T)

I don't understand this error because T is defined as extending Model, so why would it say T is not applicable?

Upvotes: 3

Views: 698

Answers (2)

biziclop
biziclop

Reputation: 49744

Your member declaration says that the values of mockStore will be lists containing an unspecified subclass* of Model.

The insertMockStore method does similarly but there's nothing guaranteeing that the subclass of Model passed to insertMockStore will be the same as the lists.

What you should do instead is declare mockStore like this:

Map<Class<? extends Model>, List<Model>> mockStore;

An easy-to-remember rule of thumb here is the "PECS rule": producer extends, consumer super. This means that if your member has a collection with type parameter Foo, all producer type methods (ones that insert into your collection) will need T extends Foo and all consumer type methods (those that return values from the collection) should have T super Foo.

*As always with generics, in "subclass" we include the class itself.

Upvotes: 6

Peter Lawrey
Peter Lawrey

Reputation: 533530

Your mockStore has List<? extends Model> values so it doesn't know if you can add a T to it.

A simpler solution is to simplify your declaration.

private final Map<Class, List> mockStore;

@SuppressWarning("unchecked")
protected void insertMockStore(Model obj) {
    mockStore.get(obj.getClass()).add(obj);
}

Upvotes: 1

Related Questions