5

I have an interface A like this:

public interface A{
    void myFirstMethod();
    void mySecondMethod();
}

And then I have this class:

public class MyClass{
    private List<? extends A> elements;

    public MyClass(){
        A obj = new A(){
            @Override
            public void myFirstMethod(){
              //SOME CODE
            }
            @Override
            public void mySecondMethod(){
              //SOME CODE
            }
        };
        elements.add(obj);
    }
}

I haven't use generics before (only things like List<String>...) so I can't see why this code doesn't compile. To be more precise, I get an error on the line elements.add(obj); that the method add is not applicable for these parameters.

EDIT: I've changed the code and now the elements.add(obj) compiles fine, but I have another problem.

public class MyClass{
    private List<A> elements;

    public MyClass(List<A> elements){
        this.elements = elements;
        elements.add(obj);
    }
}

When I try to do this, it doesn't compile.

//A1 implements A
List<A1> list = new ArrayList<A1>();
MyClass(list);

How could I fix this?

1 Answer 1

9

Imagine that you have two subclasses:

class A1 implements A {...}
class A2 implements A {...}

Then you could write:

List<? extends A> elements = new ArrayList<A1>(); // a list of A1

But then this should not compile:

elements.add(new A2()); //oops: an A2 is not an A1

For that reason, you can't add anything but null to a List<? extends A> because you don't know what actual generic type it is. In other words, ? extends A means a specific, but unknown, subtype of A (or A itself).

In your case, a List<A> would probably do what you expect - you would be able to add some A1s and some A2s to it.

Sign up to request clarification or add additional context in comments.

5 Comments

In other words: ? means "unknown", not "any".
That's right; the notation List<? extends A> means that it's a List of some specific but unknown type. It does not mean that the list can contain a mixture of different types of objects that extend A; it means that the list contains objects of some definite type that extends A, but you don't know what the actual type is.
Just a follow up on it, I understood but just tried with something weird like, List<? extends A> elements = new ArrayList<A>(); This line is working, but again when I try to add an object of A1, elements.add(new A1()); it shows error. I can understand the error, but my question is why Java is allowing me at first place to write something like the first line.. new ArrayList<A>();
If you want to add something into generic collection of type A, use the List<? super A>.
@sakura Yes, that won't work, exactly because of what we're explaining. The compiler looks at the type of the variable elements, which is List<? extends A>. From that type alone, the compiler doesn't know what the exact type is of the elements in the list; it only knows that they are of some unknown type that extends A. Since it doesn't know what the type really is, you can't add anything to the list - because it's impossible for the compiler to tell whether what you try to put in is of a valid type or not. It does not matter that you initialize your variable with new ArrayList<A>.

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.