Reference declared as List<
? super Integer> can point List containing objects of unknown type, which is a supertype of Integer. It could be List<
Object>, List<
Comparable>, List<
Serializable>, List<
Number> or List<
Integer> (any of them).
When you call List.add() in this case you can safely do it only using Integer instance, which
IS-A contemporary Object, Number, Serializable, Comparable and Integer. Regardless of which supertype of Integer is used in particular listOne initialization (you have chosen ArrayList<Integer>, but it could be ie. ArrayList<Serializable>), add() method can always be called with Integer instance. In contrary you could not call listOne.add(new Object()) when declared listOne reference as List<? extends Integer>, because this declaration could mean List<Comparable>, and Object cannot be cast to Comparable when using add() method (like Integer could be).
Here you declared listTwo as List of unknown types extending Integer. Let's suppose Integer is not final, and have subclass called SubInteger. List<
? extends Integer> could be List<
Integer> or List<
SubInteger>. If it is List<SubInteger> you could not call add(Integer), because Integer is not SubInteger (SubInteger IS-A Integer, but not vice versa). It may look strange because we can see that listTwo is initialized as ArrayList<Integer> and not as ArrayList<SubInteger> (so we know the type is Integer not SubInteger), but please notice, that add() method is called on reference declared as List <? extends Integer> (uknown type).
Rachid Aourich wrote:
in that case i dont see the utility of that Instantiation [ArrayList<?> myList=new ArrayList<String>(); ] :
take a look here:
https://coderanch.com/t/559717/java-programmer-SCJP/certification/List
regards
t.