Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<? extends Base> VS List<Base>

Tags:

java

generics

List<? extends Base> list

List<Base> list

Is there any difference between the two declarations?

Thanks,

like image 702
user113454 Avatar asked Feb 28 '12 19:02

user113454


People also ask

Are List <?> And List <? Extends object the same?

Both are the same because all objects in Java extend Object . I would prefer List<?> because it's more concise. Save this answer.

Is List Integer a subtype of List Number?

Although Integer is a subtype of Number, List<Integer> is not a subtype of List<Number> and, in fact, these two types are not related.

What does question mark mean in Java generics?

In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific).

Is Integer a subtype of Double Java?

type 'int' is not a subtype of type 'double'


2 Answers

List<Base> list can contain elements of type Base or any of its subtypes. Some example with the JDK classes:

List<Object> objects = new ArrayList<Object>();
objects.add(new Object()); // adding an Object instance
objects.add("I am a String"); // a String instance is also an Object
objects.add(Integer.valueOf(5)); // an Integer instance is also an Object

But when you retrieve the elements, you can assign them only to variables of the Object class, because Object is the type parameter of the declared list.

Object first = objects.get(1);
Object second = objects.get(2);
Object third = objects.get(3);

Their real runtime classes are still Object, String and Integer, so you can cast them to those types and work with them as such, but such casts may fail at runtime with a ClassCastException if not done right and it's generally not a good idea to work with lists in such fashion.

List<? extends Base> list is a declaration that is not actually designated for declaring variables, because as already mentioned in Daniel Pryden's comment - you cannot add() any object in it, only nulls.

List<? extends String> list = new ArrayList<? extends String>();
list.add("a String")); // compile error!

But you can use such a bounded wildcard expression for generic method parameters. An example from the List itself is the addAll() method whose signature is this:

boolean addAll(Collection<? extends E> c);

This enables you to do something like this:

List<String> strings = Arrays.asList("a", "b");
List<Object> objects = new ArrayList<Object>();
objects.addAll(strings);

Without the <? extend E> wildcard it wouldn't be possible to add those Strings into the List of Objects, because generic types (unlike arrays) are not covariant. That means that a List<String> is not a subtype of List<Object>. But any String is an Object, right? So therefore it is necessary to declare the method parameter with the bounded wildcard - a List<String> is a subtype of List<? extends Object>.

Again, I have to point out - the bounded wildcard are primarily designated for generic method parameters, not for method return types or variable declarations.

like image 127
Natix Avatar answered Oct 09 '22 17:10

Natix


Yes.

List<Base> can contain a mixture of different things that all derive from Base. List<? extend Base> contains homogeneous items (in the sense that they must all derive from some specific, unknown type that in turn derives from Base).

Put another way, List<? extends Base> is the base class for List<T extends Base>. So you can pass a List<T extends Base> to any method that takes a List<? extends Base>. The same is not true for methods that take a List<Base>.

like image 27
Oliver Charlesworth Avatar answered Oct 09 '22 17:10

Oliver Charlesworth