Generics in Java

As code re-usability is an important characteristic of any object-oriented language. For example,class inheritance provides re-usability of a class. J2SE 5.0 takes re-usability to the next level by introducing a very powerful feature called generic programming, which enables you to write code that can be reused for different types of objects.

In this post I am going to explore generic programming from the perspective of collections. 

Generic Collections

When you retrieve an element from a collection, you need to cast it to the right type. If you make a type mistake in casting, the compiler will not catch it, but you will get a runtime error. It is desired that the errors be caught during compilation and not when the application is running. The solution to this problem is provided by the generic collections introduced in J2SE 5.0, which provide a way for you to declare the type of a collection so that the compiler can check it. You can still use the non-generic collections and they will work. However, using generic collections is less error prone.

For example, consider the following code snippet:

     ArrayList myList = new ArrayList();
     String st = "Flemingo";
     String st1 = (String) myList.get(0);

This is perfectly fine code for non-generic collections and will compile and run even in J2SE 5.0 and generate the following output:

However, it will generate a compiler error if you replace line 4 with the following line:

     String st1 = myList.get(0);
That means the compiler requires you to cast to a type. However, it has no way of ensuring that you are casting to a correct type, as long as you are casting to an object. For example, the code will compile without an error if you replace line 4 with the following line: 
    Integer st1 = (Integer) myList.get(0);

Of course, you will get an exception at runtime. We can rewrite the same code fragment in generic collections as shown here:            

      ArrayList<String> myList = new ArrayList()<String>;
      String st = "Flemingo";
      String st1 = myList.get(0);

Note that line 4 does not have any explicit casting. However, it will still accept the correct cast, but it’s not required. Unlike the non-generic collections, here the compiler will not let you cast incorrectly. For example, you will receive a compiler error if you replace line 4 with the following line:

        Integer st1 = (Integer) myList.get(0);

This has become possible due to line 1, where you have declared the type of the myList collection elements as String. You could have declared any object reference type. It’s important that you get used to the angle bracket notation: when you see something like <E>, read it as of type E. The overall result of using generics, especially in large applications, is improved readability, robustness, and reliability. Below code snippet presents a complete code example to demonstrate the use of generic collections using ArrayList. Of course, the same principles apply to any Collection implementation.

public static void main(String[] args) {
       ArrayList<String> myList = new ArrayList<String>();
       String st1 = "ready";
       String st2 = "set";
       String st3 = "go";

       String st;
       Iterator<String> itr = myList.iterator();
       while (itr.hasNext()) {
              st =;

The output of Code Snippet is:


Note that the iterator in line 12 has been declared of type String. This is essential, because otherwise the compiler will generate an error.

Generic programming goes beyond just collections and has a more general dimension to it: instead of specifying a type in a class or in a method, you can just say some type in a generic way, and then specify it at a later time.  

Reference(s): SCJP Exam for J2SE 5

No comments:

Post a Comment