Archive for June, 2013

This is a continuation of my introductory tutorial on Generics. Previous posts in this series can be found here.

Why should we use Generics

I intended to write about this after I’ve demonstrated some generics examples so that their usefulness become apparent to the readers. So let’s see what the official tutorial of Java has to say about the usefulness of generics, or, why should we use them –

  1. Stronger type checks at compile time
  2. Elimination of casts
  3. Enabling programmers to implement generic algorithms

The first two are very closely related. We have already seen how generics allow us to write generic algorithms. It’s time to focus on the first two.

Point number one – stronger type checks at compile time

Generics were specifically introduced to work with the Java Collections API. Before generics era, Lists and ArrayLists didn’t use generics, and were used like this –

/* Create a list to hold some
 * string values.
 */
List myList = new ArrayList();

myList.add("Hello ");
myList.add("World ");
myList.add("from Java");
myList.add(1);    // Oh no...

Iterator it = myList.iterator();
while(it.hasNext()) {
  String s = (String ) it.next();
  System.out.print(s);
}

If you are new to Collections, don’t worry, they are not that hard to learn. For the time being, you can simply consider myList to be something like an array, or a collection, where we can add elements using the add method, and later traverse them using a standard iterator.

This is how we used collections in the pre-generic era. To be used as a collection for any types, the add method expects an Object as its argument and casts/boxes any other types to it. As you can see from the above code, one can easily put integers into a collection of strings if they are not careful enough, just like we did in line number 9. In this case the program will compile without any trouble, but we will get a ClassCastException at runtime at line number 13, because we cannot cast an integer into a string.

Some people might consider my example far-fetched, saying that the scenario described above is less likely to occur in real world. I would like to tell them that the above scenario is a very simplified one. For example, you might call a library method in your program which returns a collection of strings, and you didn’t know it in advance and put integers in that list, resulting in runtime exception. If this is also not convincing, consider the Date class in Java which is defined in two different packages – java.util and java.sql, and mixing them together in the same collection will likely result in a runtime exception. It was programmer’s responsibility to make sure that a collection didn’t contain elements from various types, and programmers did make those mistakes.

When we use generics, the above problem doesn’t occur. Now it’s the compiler’s responsibility to make sure that a collection doesn’t get polluted by containing elements from more than one type. When we try to put an integer into a collection of strings, compiler will generate an error at compile time, rather than at runtime –

/* Create a list to hold some
 * string values.
 */
List<String> myList = new ArrayList<String>();

myList.add("Hello ");
myList.add("World ");
myList.add("from Java");
myList.add(1);    // Now this is a compile time error

Iterator<String> it = myList.iterator();
while(it.hasNext()) {
  String s = it.next();
  System.out.print(s);
}

Using generics in this way ensures that our list will contain only elements of a certain type, and we will not run into any runtime exception. From the java best practice guidelines, we know that catching and fixing errors at compile time is much easier than catching them at runtime (more on this in a future article).

Point number two – elimination of casts

If you check out the second example, you’ll see that the cast at line number 13 is no longer required. This is because when we used generics, we have explicitly told the compiler that this collection will only contain a collection of strings. We will add only strings to it, and we will retrieve only string values from it. If you could check the method signature of the next method now (just like I did using Eclipse by hovering the cursor over this method), you’ll see that it too returns a string value where in the first example it returned an object of type Object. Eliminating cast this way also helps us to reduce the possibility of encountering any runtime exception (although implicitly this is a consequence of the first point).

Point number three – enabling programmers to implement generic algorithms

I have already explained this point in the previous two articles. If like to visit them again, here is the first one and here is the second one :-).

With the above three usefulness, I’d like to mention another one which I have described below.

Point number four – enabling programmers to write clear and concise code

Let’s write a simple program – put five numbers into a list and add them together. Here’s how we did it before generics were introduced –

List intList = Arrays.asList(new Integer[] {
    new Integer(1), new Integer(2), new Integer(3),
    new Integer(4), new Integer(5)
});
int sum = 0;

Iterator it = intList.iterator();
while(it.hasNext()) {
    sum += ((Integer) it.next()).intValue();
}

System.out.println("The sum is: " + sum);

Reading this code is not too easy. It’s also not expressive, as we cannot tell what types of elements we intend to store in our list.

If we write the same code using generics, then it becomes something like this –

List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5); // We can do this
                                                      // because of Autoboxing
int sum = 0;

for (int i: intList) {
    sum += i;
}

System.out.println("The sum is: " + sum);

You can probably read this code without much explanation. It’s clear and much shorter from it’s non-generic counterpart. Here we have made use of couple of other Java language features – the for-each loop and autoboxing/unboxing. Indeed generics work well with these features.

I hope you are now convinced about generics :-).

That’s it for today. Hope to write another post real soon. Stay tuned!

Additional Resources