Can anyone give me an explanation on the following..
List<? extends Shape> typeList = new ArrayList<>();
List<Shape> shapeList = new ArrayList<>();
typeList.addAll(shapeList); //1
typeList = shapeList; //2
Here 'line 1' will not compile because typeList is defined to take some class that extends Shape. However the compiler doesn't know which class. Therefore the compilation fails.
The same logic applies to 'line 2'. How shapeList can be assigned to typeList? Why this line is not giving compilation error?
When you declare as the list type ? extends Shape
you can read Shape
objects from the list. But not write to it. So the list or data structure becomes read only. That is why addAll
does not compile.
Whereas when you use ? super Shape
the list becomes write only. So if you replace in your code with ? super Shape
your code will compile.
See this article on co-variance and contra-variance:
https://dzone.com/articles/covariance-and-contravariance
For contravariance we use a different wildcard called ? super T, where T is our base type. With contravariance we can do the opposite. We can put things into a generic structure, but we cannot read anything out of it.