http://www.developer.com/lang/article.php/3831971/Catch-Errors-at-Compile-Time-with-Java-Generics.htm
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. 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.
When you try to run Listing 2, you end up with the following ClassCastException.
Here is how you would handle the code example using generics:
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.
The introduction of generics has greatly improved code readability. Anyone who uses the code understands what types of inputs are essential for the integration efforts. For example, when Listing 3 is rewritten as Listing 4 below, the compiler throws errors during compilation.
The compilation of Listing 4 fails with the following error message.
Assuming you have an ArrayList that has elements of unknown data types, you can simply employ the wildcard and start using the ArrayList in your application. Typical usage will be something like Listing 5. If you look carefully, the computeSum() method takes an argument of List, which is of unknown type, extending Number. The method is used for achieving the same action for both types (integer and double) of arguments. Using the unknown type is a little tricky and may not be clear in all your use cases. See the generics documentation for more information.
Good programming does not mean that you need to use complex development techniques. The simple, easy-to-understand code that you can produce with generics will be maintainable by others, which can make everyone's life easier when issues arise while you're not on premise. Others can debug your code easily in your absence.
Catch Errors at Compile Time with Java Generics
July 28, 2009
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);
}
}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.
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);
}
}
Code Readability
The following are examples of declaring objects to hold data:
//dataList will hold objects of type integer
List
Listing 4: Code Using Generics and Has an Exception
import java.util.*;
public class GenericsWithExp
{
public static void main(String args[])
{
GenericsWithExp genericsWithExp = new GenericsWithExp();
genericsWithExp.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 String("5")); //Adding a String object
Integer value = dataList.iterator().next();
//Retrieving the next value and assigning accordingly
System.out.println("Retrieved value: "+value);
}
}Generics Wildcards
If you do not know what type of data your collection is holding, then you can use a wildcard (<?>) in the placeholder for generics to indicate that the data type is unknown.
Listing 5: Generics Using Wild Cards
import java.util.*;
public class GenericsWithWildCard
{
public static void main(String args[])
{
GenericsWithWildCard genericsWithWildCard = new GenericsWithWildCard();
List<Integer> intValueList = genericsWithWildCard.buildIntegerList();
System.out.println("Sum of Integer arguments: " +(int)genericsWithWildCard.computeSum(intValueList));
List<Double> doubleValueList = genericsWithWildCard.buildDoubleList();
System.out.println("Sum of Double arguments: " +genericsWithWildCard.computeSum(doubleValueList));
}
private List buildIntegerList()
{
List<Integer> dataList = new ArrayList<Integer>();
dataList.add(new Integer(12));
dataList.add(new Integer(7));
return dataList;
}
private List buildDoubleList()
{
List<Double> dataList = new ArrayList<Double>();
dataList.add(new Double(11.4));
dataList.add(new Double(6.3));
return dataList;
}
private double computeSum(List<? extends Number> valueListArg)
{
double sum = 0;
for (Object i : valueListArg)
{
if(i instanceof Integer)
{
sum += (Integer) i;
}
else if(i instanceof Double)
{
sum += (Double) i;
}
else
{
System.out.println("Not an valid Integer/Double argument: "+i);
}
}
return sum;
}
}
Code Download
For Further Reading
About the Author
Sridhar M S is a Java developer from Bangalore, India. He holds a master's degree in Computer Science.