3

The method add(capture#2-of ? extends IObject) in the type List is not applicable for the arguments (IDerived)

protected List<? extends IObject> getObjects()
{
    List<? extends IObject> objects = new ArrayList<IObject>();
    for (String id: item_ids)
    {
        IDerived object = (IDerived) readObject(id);
        objects.add(object); #error
    }
    return objects;
}

interface IDerived extends interface IVersionedObject extends interface IObject

If I change the type of objects to List then the error goes away, which makes no sense because it has to make exactly the same cast to the function return type.

4
  • 2
    Shouldn't your objects be instantiated as new ArrayList<IDerived>()? Commented Feb 4, 2011 at 18:45
  • @biziclop, why not post that as an answer? Commented Feb 4, 2011 at 18:53
  • I might have went overboard with my answer. I thought you where asking why vs how-to-fix-it. Commented Feb 4, 2011 at 18:58
  • 1
    @finnw Because I didn't have Eclipse at hand to test that it compiles and I had no time to write up an explanation. Commented Feb 4, 2011 at 19:08

3 Answers 3

7

Try this:

protected <T extends IObject> List<T> getObjects() {
    List<T> objects = new ArrayList<T>();
    for (String id: item_ids)
    {
        T object = (T) readObject(id);
        objects.add(object); // NO error
    }
    return objects;
}

EDIT (short explanation):

This way your method will work fine with any subtype of IObject (the lists and casts inside get to be generic) and the return type will be inferred from the caller's expectations (as you apparently intended).

In response to the comment, you can now call the getObjects() method in the following ways:

// This should only be used if readObject() behaves like
// getObjects() and is able to return any requested subtype.
// Otherwise, you'll get a ClassCastException when trying to get
// something from the derivedList in case readObject() put something
// else there (which is not a subtype of IDerived).
List<IDerived> derivedList = getObjects();

// This is the safe way to go in case you don't have
// full control over what readObject() returns.
// But if you're using it like this (all the time), you'd better
// return List<IObject> from getObjects() and get rid
// of generics.
List<? extends IObject> objectList1 = getObjects();
List<IObject> objectList2 = getObjects();
Sign up to request clarification or add additional context in comments.

2 Comments

+1...and the caller can always cast/store the result as a List<? extends IObject> anyway if that's really what they want.
Oh wait I didn't see the unchecked cast in the middle there. That's a bit yuck.
4

I don't know if I am going to explain this right but here I go.

List<? extends IObject> objects = new ArrayList<IObject>();

Says that the list is of an unknown type that extends IObject. Even though you put a new ArrayList<IObject>(); on the rhs, the list generic type is still not tightly defined. In other words, the generic type does not get "baked" in when you assign a reference to it.

So, when you call objects.add(object); The type checker doesn't know that the list will be compatible with IDerived because the list could be of type IVersionedObjectSomethingElse. Even though that's impossible from you flow of logic it's possible to constuct.

List<? extends IObject> objects = null;
if (test) { 
    objects = new ArrayList<IObject>();
}
else {
    objects = new ArrayList<IVersionedObject2>();
}

objects.add( (IDerived) iDerivedObj ); // iDerived *might* not be compatible

Comments

-1

Why the wildcards? Instead of ? extends IObject, use IDerived

Change this line

List<? extends IObject> objects = new ArrayList<IObject>();

to this:

List<IDerived> objects = new ArrayList<IDerived>();

And change

protected List<? extends IObject> getObjects()

to

protected List<IDerived> getObjects()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.