before Java 5 there was no syntax for declaring a type safe collection. To make an ArrayList of Strings, you said,
ArrayList myList = new ArrayList();
or, the polymorphic equivalent
List myList = new ArrayList();
There was no syntax that let you specify that myList will take Strings and only Strings.
As of Java 5, we can use generics, and while they aren’t only for making type safe collections, that’s just about all most developers use generics for.
Here’s a review of a pre-Java 5 ArrayList intended to hold Strings. (We say “intended” because that’s about all you had—good intentions—to make sure that the ArrayList would hold only Strings).
List myList = new ArrayList(); // can’t declare a type
myList.add(“Fred”); // OK, it will hold Strings
myList.add(new Dog()); // and it will hold Dogs too
myList.add(new Integer(42)); // and Integers…
A non-generic collection can hold any kind of object! A non-generic collection is quite happy to hold anything that is NOT a primitive.
And since a collection could hold anything, the methods that get objects out of the collection could have only one kind of return type—java.lang.Object. That meant that getting a String back out of our only-Strings-intended list required a cast:
String s = (String) myList.get(0);
And since you couldn’t guarantee that what was coming out really was a String.
So, generics takes care of both ends (the putting in and getting out) by enforcing the type of your collections. Let’s update the String list:
List<String> myList = new ArrayList<String>();
myList.add(“Fred”);// OK, it will hold Strings
myList.add(new Dog());// compiler error!!
Perfect. That’s exactly what we want. By using generics syntax—which means putting the type in angle brackets <String>, we’re telling the compiler that this collection can hold only String objects. The type in angle brackets is referred to as either the “parameterized type,” “type parameter,” or of course just old-fashioned “type.”
So, now that what you put IN is guaranteed, you can also guarantee what comes OUT, and that means you can get rid of the cast when you get something from the collection. Instead of
String s = (String)myList.get(0);// pre-generics, when a String wasn’t guaranteed
we can now just say
String s = myList.get(0);
The compiler already knows that myList contains only things that can be assigned to a String reference, so now there’s no need for a cast.