HimanshuR
HimanshuR

Reputation: 1428

List<interfaceI> vs List<? extends InterfaceI> in java

Arraylist with List<interfaceI> and List<? extends InterfaceI> both will have objects of classes implementing interfaceI. Then when what should be used?

Upvotes: 6

Views: 127

Answers (3)

sky
sky

Reputation: 93

here in place of this

public double max(List<? extends Number> list){

if you do like-

public List myList(List<? extends String> list){
list.add("string");// No, can not add anything in list except null
list.add(null);
}

Upvotes: 0

Antoniossss
Antoniossss

Reputation: 32507

The difference is that if you declare your list as List<? extends S> myList, the myList variable can by list of any type that extends S so associations like shown below will work:

public class Clazz implements S{}
List<? extends S> myList = new List<Clazz>(); // its fine as Clazz extends S
List<? extends S> myList = new List<S>(); // its fine as well
List<? extends S> myList = new List<Object>(); // ooooops it wil not work

But in such case you will not be abe to PUT anything to such list as you cannot guarantee the exact type of object that is held by list implementation assigned to myList

If you declare List<S> myList than you will be able to PUT and GET objects from list, as you are sure what is in it, however assignments from above will not work!

public class Clazz implements S{}
List<S> myList = new List<Clazz>(); // no way! 
List<S> myList = new List<S>(); //thats perfectly fine! - You can PUT new S in it;
List<S> myList = new List<Object>(); //known result;

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691655

Suppose Foo and Bar are two classes implementing InterfaceI.

The second one (List<? extends InterfaceI>) doesn't allow adding anything to the list (except null), since the type that the list contains is unknown: it could be a List<Foo> or a List<Bar>: you just don't know.

So you usually use this notation for a method argument, when you want the method to read the elements of the list passed as argument, and want the caller to be able to call your method with a List<InterfaceI>, a List<Foo> or a List<Bar>. Using List<InterfaceI> as argument would only accept lists of type List<InterfaceI>.

Let's take a concrete example: you want to compute the maximum double value of a list of numbers. Such a method doesn't need to add or set anything to the list. All it does is iterating on the elements, get each number and compute their maximum. The signature could be

 public double max(List<Number> list);

But then, you won't be able to do

List<Integer> ints = new ArrayList<>();
max(ints);

The only way to call this method is to do

List<Number> ints = new ArrayList<>();
max(ints);

Whereas if you declare the method as

public double max(List<? extends Number> list);

then you can do

List<Integer> ints = new ArrayList<>();
List<Long> longs = new ArrayList<>();
max(ints);
max(longs)

Upvotes: 9

Related Questions