Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can elements be added to a wildcard generic collection?

Tags:

java

generics

Why do I get compiler errors with this Java code?

1  public List<? extends Foo> getFoos()
2  {
3    List<? extends Foo> foos = new ArrayList<? extends Foo>();
4    foos.add(new SubFoo());
5    return foos;
6  }

Where 'SubFoo' is a concrete class that implements Foo, and Foo is an interface.

Errors I get with this code:

  • On Line 3: "Cannot instantiate ArrayList<? extends Foo>"
  • On Line 4: "The method add(capture#1-of ? extends Foo) in the type List<capture#1-of ? extends Foo> is not applicable for the arguments (SubFoo)"

Update: Thanks to Jeff C, I can change Line 3 to say "new ArrayList<Foo>();". But I'm still having the issue with Line 4.

like image 675
David Koelle Avatar asked Oct 06 '08 22:10

David Koelle


People also ask

How do you add an element to a generic List in Java?

Accessing a Generic List. You can get and insert the elements of a generic List like this: List<String> list = new ArrayList<String>; String string1 = "a string"; list. add(string1); String string2 = list.

How do you use generic wildcards?

Guidelines for Wildcards. Upper bound wildcard − If a variable is of in category, use extends keyword with wildcard. Lower bound wildcard − If a variable is of out category, use super keyword with wildcard. Unbounded wildcard − If a variable can be accessed using Object class method then use an unbound wildcard.

What are wildcards in generics?

The question mark (?) is known as the wildcard in generic programming. It represents an unknown type. The wildcard can be used in a variety of situations such as the type of a parameter, field, or local variable; sometimes as a return type.

Why are wildcards used in generics?

The wildcard is useful to remove the incompatibility between different instantiations of a generic type. This incompatibility is removed by using wildcards ? as an actual type parameter.


1 Answers

Use this instead:

1  public List<? extends Foo> getFoos()
2  {
3    List<Foo> foos = new ArrayList<Foo>(); /* Or List<SubFoo> */
4    foos.add(new SubFoo());
5    return foos;
6  }

Once you declare foos as List<? extends Foo>, the compiler doesn't know that it's safe to add a SubFoo. What if an ArrayList<AltFoo> had been assigned to foos? That would be a valid assignment, but adding a SubFoo would pollute the collection.

like image 145
erickson Avatar answered Sep 28 '22 08:09

erickson