Reputation: 1428
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
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
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
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