While it is true that generic data is erased at compile-time, that doesn't mean they are totally useless. The only line that would compile in your example is the last one, but you would get a warning that you are using RawType
s. A RawType
is a generic class that does not have a generic object. The first two lines are only half-built.
The reason you pretty much have to use generics is that the list is type-safe. If you use generics, you could use something like this:
List<String> list = new ArrayList<>();
String out = list.get(0);
If you use raw types, you would have to do this:
List list = new ArrayList();
String out = (String) list.get(0);
This may seem OK, but what if you add
a value to the list that is not a String
? The program crashes. For example:
List unsafe = new ArrayList();
List<String> safe = new ArrayList<>();
unsafe.add("hi");
unsafe.add(new Tree());
safe.add("hi");
safe.add(new Tree()); // This line would throw an exception.
String out = (String) unsafe.get(0);
String out1 = safe.get(0);
String out2 = (String) unsafe.get(1); // This line would throw an exception.
If you still don't quite see why to use generic types, the final nail in the coffin for raw types is this: If my (String) unsafe.get(1)
is in a separate class, on the hundredth line, I know that that line is the problematic line. I, however, don't know where the non-string object is being added, only where it's being accessed.
If you use generic types, you know exactly where the problematic addition is made, and you can prevent it.