List <interfaceI> vs List <? extends InterfaceI> in java
Suppose Foo and Bar are two classes that implement InterfaceI .
The second ( List<? extends InterfaceI> ) does not allow adding anything to the list (except null), because the type that contains the list is unknown: it can be List<Foo> or List<Bar> : you just donβt know.
So you usually use this notation for the argument when you want the method to read the elements of the list passed as the argument, and want the calling caller to call your method using List<InterfaceI> , a List<Foo> or List<Bar> . Using List<InterfaceI> as an argument will only accept lists of type List<InterfaceI> .
Take a concrete example: you want to calculate the maximum double value of a list of numbers. This method does not need to add or install anything to the list. All he does is iterate over the elements, get each number and calculate their maximum. Signature may be
public double max(List<Number> list); But then you cannot 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); If you declare a 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) The difference is that if you declare your list as List<? extends S> myList List<? extends S> myList , the variable myList can list any type that extends S , associations will work, as shown below:
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 this case, you will not enter into the PUT anything in such a list, since you cannot guarantee the exact type of object that is held by the implementation of the list assigned by myList
If you declare a List<S> myList , than you can PUT and GET objects from the list, since you are sure that it 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;