ExerciseDifficulty: Advanced1 min

Six Lines: Which Ones Does the Compiler Refuse

Six lines. Decide which compile and which do not, and why. All six before the reveal.

java
List<String> strings = new ArrayList<>();

// 1
List<Object> objects = strings;
// 2
List<?> anything = strings;
// 3
anything.add("more");
// 4
Object first = anything.get(0);
// 5
List<? extends Number> numbers = new ArrayList<Integer>();
// 6
numbers.add(1);
Which of the six compile?
Each line, whether it compiles, and why
Compiles?Why
1NoA list of a subtype is not a list of the supertype — adding anything would break it
2YesA wildcard accepts a list of anything
3NoNothing is known about the element type, so nothing is safe to add
4YesEvery element is at least an Object, so reading one is safe
5YesInteger is a subtype of Number, which is what extends accepts
6Noextends means the list might be of some other subtype, so adding is refused

Lines three and four together are the whole of what a wildcard means. You may take things out as Object and you may not put anything in, because the compiler knows the list has some element type and not which one.

Line six is the one people argue with. numbers might be pointing at a List<Double>, and adding an Integer to it would be exactly the corruption generics exist to prevent.