0

How can I specify that I want any object that implements the A interface to be allowed inside of the List in a type-safe manner? I want to be able to invoke a given method of A over all of the objects, regarding what Class type they are.

public interface A (){}

List<? extends A> myList = new ArrayList<? extends A>();

I am getting: Cannot instantiate the type ArrayList<? extends A>

If I leave the generic off of the instantiation side it works fine, but I have to specify @SuppressWarnings({ "rawtypes", "unchecked" }) to make the compiler hush up about the warnings.

5 Answers 5

3

To see why it doesn't make sense to instantiate a new ArrayList<? extends A>(), in fact we can equivalently create a new ArrayList<B>() with any arbitrary class or interface B (even one that is not related to any of your objects) that implements A, and the resulting created ArrayList can be safely assigned to a variable of type ArrayList<? extends A>. Then you might wonder, oh, this is stupid, because the objects I want to put into it are not of class B, so how can this be the same? But it is the same, because you cannot put anything into a reference of type Something<? extends A> anyway. This is why it doesn't make sense to create a new ArrayList<? extends A>().

How can I specify that I want any object that implements the A interface to be allowed inside of the List in a type-safe manner? I want to be able to invoke a given method of A over all of the objects, regarding what Class type they are.

That's exactly what ArrayList<A> is. It allows all instances of A (of course all objects that implement A are instances of A) and you can use any methods of A on them. Something like this is what you want:

List<A> myList = new ArrayList<A>();

Something like List<? extends A> is only used in cases when you will get a List object from some other code, and you don't know (or care) what exactly is the generic parameter they created it with. (In such a case you cannot put objects into the List.) This is completely different from your case here, where you are creating the List object, so you decide and therefore know exactly what generic parameter is used.

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

Comments

2

The issue is not related to binding a type parameter to an interface, but that you can't instantiate a parameterized type with a wildcard. new ArrayList<? extends A>() or even new ArrayList<?>() doesn't make sense because you're not telling the compiler what the instantiated List actually holds. new ArrayList<A>() on the other hand would make sense.

2 Comments

So are you saying there is no solution to my question? You can not specify this?
When you instantiate the List, you must specify exactly what type of elements it holds. This might be new ArrayList<A>() or new ArrayList<Foo>() where Foo implements A. If you want more help, we will need to see the code that led you to this situation.
1

just List<A> is fine this allows objects that implement A in the list and that all objects in the list implement A

Comments

0

I think you are looking for:

List<? super A> myList = new ArrayList<A>();
  1. List<? extends A> myList ... that is telling the compiler that it is a list of some unspecified type and the unspecified type extends A. You can't put any A in this list because it might not be the right exact type. All the compiler knows is that any object in this list must be an A. I think you want List<? super A> myList. This is telling the compiler that List is of some unspecified type of which A extends. Now the compiler can let me put any A in the list.
  2. new ArrayList<? extends A>(); is just plain wrong.

5 Comments

While this compiles, when you iterate over the objects you can not do so in a type-safe manner. The list returns Object. I'd like to be able to say A instance = myList.get(0);
Then I would guess List<A> myList = new ArrayList<A>() would be better.
^ This works, I thought when using interfaces with generics you needed to specify <? extends {interface}>? Guess not! I got my information from francisoud.blogspot.com/2007/09/…
Writing T extends A in a type parameter for a class or method declaration is different from writing ? extends A in a variable declaration. The former is what the article is demonstrating.
It is not necessary. <? extends A> means some unspecified type that extends A. It is most useful for constructs like <? extends Runnable & Comparable<Integer>> where you are specifying that the list is composed of elements that implement 2 or more interfaces. It is not as helpful in your case.
0

You want

List <A> collection = new ArrayList <A> ();

By using the wildcard you are suppressing information to the compiler. You say you want to be able to both read and write to the 'List'. A generic '? super A' lets you write to the collection but not read from it. A generic '? extends A' lets you read from the collection but not write to it. Putting just 'A' in the generic parameter lets you both read from and write to the collection. See the free chapter from Joshua Bloch's seminal Effective Java on generics at http://java.sun.com/docs/books/effective/generics.pdf.

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.