October 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Catch Errors at Compile Time with Java Generics

  • July 28, 2009
  • By Sridhar M S
  • Send Email »
  • More Articles »

Imagine this scenario the day before releasing your software. While doing some final rounds of verification, your team discovers the nightmare of ClassCastException in the java.lang package. This typically occurs when you try to type cast entities of different types. For example, assigning a string to an integer will lead to this exception, thereby bringing the whole application to a standstill.

You can prevent such showstoppers if you use the generics feature introduced in J2SE 5. Using generics in your Java development can help you detect issues during compile time rather than being confronted by them at run time. This gives you greater control of the code and makes the syntax easy to follow. Generics also improves code readability.

Going back to the ClassCastException, does Java 5 convert the string value to an integer even though it is a non-integer? No. All possible data casting errors are determined during compile time. During compilation, it will ensure that you use the right types during object creation, and hence, Java 5 takes care of casting also. You do not have to explicitly cast the data every time you want to use them.

How Does the Code Work?

The code listings in this section detail the existing methodology and the generics method, and the discussion explains the differences between them.
Listing 1: Code Without Using Generics
 
import java.util.*;
 
public class NoGenerics
{
    public static void main(String args[])
    {
       NoGenerics noGenerics = new NoGenerics();
       noGenerics.initialize();
    }
 
    private void initialize()
    {
       List dataList = new ArrayList(); 
//Creating a new ArrayList to hold integers. //Even though the intention is to hold integer types,
there is no place to explicitly specify this dataList.add(new Integer(5)); //Adding an Integer object Integer value = (Integer) dataList.iterator().next();
//Retrieving the next value and assigning accordingly System.out.println("Retrieved value: "+value); } }

The coding style in Listing 1 is very common. Java developers have coded this way for a long time. However, as discussed previously, a problem can occur when you replace the the line dataList.add(new Integer(5)) with dataList.add(new String("5")). Listing 2 shows the code with this change.

Listing 2: Coding Without Using Generics Causes an Exception
 
import java.util.*;
 
public class NoGenericsWithExp
{
    public static void main(String args[])
    {
       NoGenericsWithExp noGenericsWithExp = new NoGenericsWithExp();
       noGenericsWithExp.initialize();
    }
 
    private void initialize()
    {
       List dataList = new ArrayList(); //Creating a new ArrayList to hold integers.
       //Even though the intention is to hold integer types, there is no place to explicitly specify this
       dataList.add(new String("5")); //Adding a String object
       Integer value = (Integer) dataList.iterator().next(); 
//Retrieving the next value and assigning accordingly System.out.println("Retrieved value: "+value); } }

Author Note: You need JDK version 1.5 or higher to compile for all further code listings.

When you try to run Listing 2, you end up with the following ClassCastException.

Just changing integer to string brought everything to a screeching halt. This is a real problem for developers who write code believing that their input will be controlled and passed as per the requirements, or who rely on sophisticated software to handle such showstoppers. The concept of generics makes your code less error prone in such scenarios.

Here is how you would handle the code example using generics:

Listing 3: Code Using Generics
 
import java.util.*;
 
public class Generics
{
    public static void main(String args[])
    {
       Generics generics = new Generics();
       generics.initialize();
    }
 
    private void initialize()
    {
       List<Integer> dataList = new ArrayList<Integer>(); //Creating a new ArrayList to hold integers.
       //Even though the intention is to hold integer types, there is no place to explicitly specify this
       dataList.add(new Integer("5")); //Adding a String object
       Integer value = dataList.iterator().next(); //Retrieving the next value and assigning accordingly
       System.out.println("Retrieved value: "+value);
    }
}

When you run Listing 3, the code will execute as expected.

To see the value that generics added, look carefully through the lines List<Integer> dataList = new ArrayList<Integer>(); and Integer value = dataList.iterator().next();. There is a newly added string in the code: <Integer>, which defines that the list is of type integer. By defining this, the compiler ensures that no other data type can be assigned to this list. If it encounters a problem, the compiler will let the developer know during compilation and the developer can fix it (in this case, by simply replacing the integer with a different data type).

If you look carefully, you'll notice another enhancement in the code. In the line Integer value = dataList.iterator().next();, the casting of the return value from the iterator is gone. The runtime is aware that you can assign only integer values and relieves the developer from that development hassle.





Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel