Card 01/ 09
Generics: Moving a Type Error From Run Time to Compile Time
A List<String> refuses the line that puts in the wrong thing, instead of failing on the line that reads it.
Generics let a class take a type as a parameter, as in List<String>: a list declared to hold strings. The compiler then checks every line that adds to the list, so a wrong element is refused where it is written instead of failing later where it is read.
Before generics, every collection held Object. Taking something out meant casting it back, and the cast was a promise nobody checked until the line ran.
List refs = new ArrayList();
refs.add("AB-1");
refs.add(42);
String first = (String) refs.get(1);In that listing, line 3 is the mistake and line 5 is where it surfaces. In a real program those two lines can sit in different classes, written months apart by different people, and the stack trace names only the second.
With a type parameter, the compiler knows what belongs in the list:
List<String> refs = new ArrayList<>();
refs.add("AB-1");
refs.add(42);
String first = refs.get(0);| Compared on | List | List<String> |
|---|---|---|
| Wrong thing added | Accepted | Refused by the compiler |
| Taking something out | Needs a cast | Needs nothing |
| Where a mistake is found | At the line that reads it | At the line that wrote it |
So generics do not make anything faster and do not change what is stored. They move a failure from the machine of whoever runs your code to the machine of whoever writes it, which is the only place a failure is cheap.
← → move through sections and cards