ExerciseDifficulty: Advanced1 min

Practice: Which Generic Assignments the Compiler Refuses

Six lines with plain types and wildcards: decide which compile, and why.

A wildcard type, one written with ? for an unnamed type, lets you read but restricts adding, and a list of a subtype is not a list of its supertype. Apply those rules to the six lines below and decide which compile, all six before opening the answer.

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, because 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
6NoThe list might hold some other subtype of Number, so adding is refused

Lines three and four together are the whole meaning of a wildcard. 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 point at a List<Double>, and adding an Integer to it would be exactly the corruption generics exist to prevent.