Wednesday, March 7, 2012

Generics in Java

Generics are an oddly-named thing in Java that associate objects stored in a Collection with a particular type. Let's take a look at a piece of code that uses a Collection to store some Strings. It uses an ArrayList. Here's the code:


import java.util.*;
public class NoGenerics{
// This is an example of what happens
// when you don't declare a class
// for a Collection using Generics.
// It won't compile!

public static void main(String[] arg){
// No Generic declaration.
ArrayList myList = new ArrayList();
String myString="Boss Moss";
String yourString="Snorkledorf";

// put the strings into the ArrayList
myList.add(myString);
myList.add(yourString);

for (String aString: myList){
// We can't do String methods on the items from myList.
if (aString.startsWith("Boss")){
System.out.println(aString + ":");
System.out.println("Make sure you spell it right!");
}
else{
System.out.println(aString + ":");
System.out.println("I am so pretty!");
}
}
}
}

What happens here to upset javac is that once the String is placed in the ArrayList, its type is lost, and it is known only as an Object. To be treated as a String again, it would have to be cast as a String. If any errors are made in casting the data, the program will fail at runtime, not when it is being compiled--when the programmer has it in their hands to fix it.

Feel free to take the above code and try to compile it to see the error you'll get. It is instructive.



The Fix for Lost Types

In Java version 1.5 "Generics" were added to fix this. Now Collections like the ArrayList can associate a type with the data put in them, and the compiler can do type checking. Here's the above code, with the Generic declaration added:


import java.util.*;

public class Generics{
// This is an example of what happens
// when you declare a data class
// for a Collection using Generics.

public static void main(String[] arg){
// Generic declaration.
ArrayList myList = new ArrayList();
String myString="Boss Moss";
String yourString="Snorkledorf";

// put the strings into the ArrayList
myList.add(myString);
myList.add(yourString);

for (String aString: myList){
// Now when we can do String methods on the List items.
if (aString.startsWith("Boss")){
System.out.println(aString + ":");
System.out.println("Make sure you spell it right!");
}
else{
System.out.println(aString + ":");
System.out.println("I am so pretty!");
}
}
}
}

Generics = Typed Collections
So if you are going to use a collection on Objects all of a specific type (rather than mixing and matching), put on a Generic declaration.
StumbleUpon