Generics and Java

The story behind the controversy

June 7, 2001— The lack of generic types in the Java programming language has been a source of controversy for years. All of that is starting to change as JSR-014, “Add Generic Types to the Java Programming Language,” makes its way through the Java Community Process (JCP). Generic types are coming to Java — one of these days.

On Tuesday at the JavaOne Conference, Gilad Bracha, computational theologist at Sun Microsystems and specification lead of JSR-014, presented the technical session entitled “Adding Generics to the Java Programming Language” (TS-2733) to a sold-out crowd. The enormous turnout — many stood outside the packed hall listening to the presentation on speakers — demonstrated the importance of the generics topic.

Generics overview

Generics are a complicated topic with deep theoretical roots. Those who are familiar with C++ know that templates — controversial in their own right — represent that language’s implementation of generics. Before giving an example of a generic, let’s take a look at a current Java example that could benefit from generics:

import java.util.*;
public class DangerousLoop 
{
    public static void main( String [] args ) 
    {
        List l = new ArrayList();
        
        Integer i1 = new Integer( 1 );
        Integer i2 = new Integer( 2 );
        String  i3 = "3";
        Integer i4 = new Integer( 4 );
        
        l.add( i1 );
        l.add( i2 );
        l.add( i3 );
        l.add( i4 );
        
        System.out.println( sum( l ) );
        
    }
    
    public static int sum( List l ) 
    {   
        Iterator numbers = l.iterator();
        
        int counter = 0;
        
        while( numbers.hasNext() )
        {
            Integer integer = (Integer) numbers.next();
            counter += integer.intValue();
        }
        
        return counter;
    }
    
}

The public static int sum( List l ) method expects a List of Integers. The method loops over each element in the List, casts it back to its expected type, and sums the value. This simple example demonstrates how you would have to handle lists in Java. However, it also exemplifies many of the shortcomings that the lack of generics brings.

First, consider the main() method that sets up the Listthat is sent to the sum() method. You will notice that main() inserts Integers and a String into the list. Of course, calling the sum90 method on this Listwill result in a ClassCastException because it will try to cast a String to an Integer.

Heterogeneous collections such as those found in Java are not type safe because you can put many different types of objects into the collection at the same time. A lack of type safety is not always a problem. However, in order to do anything beyond the methods defined on the Object base class, you will have to cast the object back to its actual type. As this example shows, such indiscriminate casts can be dangerous. You can do an instance of check to avoid the ClassCastException; however, this extra check can add weight to your code (and is not very object oriented, for that matter).

Extra casting is also a performance problem, and it clutters the readability of code. All in all, a lack of generics results in extra headaches for the developer.

The next example presents a new List that takes advantage of generics. (Please note that this List‘s interface is simplified for brevity’s sake):

public class List<T> 
{
    public void put( T element ) { // implementation cut for brevity
    public T get( int index ) { // implementation cut for brevity
    public int size() { // implementation cut for brevity
    // other interesting methods
}

The first difference you will notice is the addition of <T>. <T> allows you to specify the type of object that the collection will hold. For this reason, this way of implementing generics is sometimes referred to as parametric polymorphism.

<T>provides for type-safe collections because the compiler can check <T> at compile time. The compiler can force you to be sure that you insert only Integersinto a List of Integers(List<Integer>).

Let’s revisit the previous example:

import java.util.*;
public class SafeLoop 
{
    public static void main( String [] args ) 
    {
        List<Integer> l = new List<Integer>();
        
        Integer i1 = new Integer( 1 );
        Integer i2 = new Integer( 2 );
        String  i3 = "3";
        Integer i4 = new Integer( 4 );
        
        l.add( i1 );
        l.add( i2 );
        l.add( i3 );   // this will now fail at compile time
                       // you won't have to wait until runtime to get an exception
        l.add( i4 );
        
        System.out.println( sum( l ) );
        
    }
    
    public static int sum( List<Integer> numbers ) 
    {   
        int counter = 0;
        
        for( int i = 0; i < numbers.size; i ++ )
        {
            Integer integer = numbers.get( i );
            counter += integer.intValue();
        }
        
        return counter;
    }
    
}

The Sum method will now accept only Lists of Integers. You will also notice that casts are no longer necessary, since get() returns T, which, in this case, is an Integer.

You will also notice that main() still attempts to insert Integers and Strings into the collection. However, when you use generics, the compiler will catch this error at compile time. While this example is fairly simple, tracking down and fixing ClassCastExceptions can be difficult. So it is much more efficient to catch them at compile time.

A note on C++

Unfortunately, generics tend to have a bad reputation because of the way C++ implements them. Bracha maintains that generics as they will appear in Java attempt to fix the shortcomings of C++ templates.

Bracha pointed out that one problem with C++ templates is code bloat. For every List<T> of type T, C++ generates a separate class. Generics as implemented by JSR-014 will not cause similar bloat: the same class and associated bytecode will work for all Lists of T.

Adding Generics to Java: An exercise in frustration

Since the beginning of Java there has been a movement to add generics to the language. After 5 years, JSR-014 hopes to finally do so. JSR-014 entered public review 2 weeks ago, with a projected August 1 close. Bracha hopes to have generics added to the language in the Tiger release (Java 1.5). However, his hopes seemed guarded.

In the session, he expressed mixed opinions toward the JCP. He said he likes the fact that the JCP allows everyone, not just Sun, to craft the direction of Java. However, in his experience, the JCP also gives everyone the opportunity to say why a feature must be delayed. As such, the JCP can slow a process down.

However, you can try generics today with the Java 1.4 beta and a prototype javac that includes support for them. A prototype for generics is available from Bracha’s Website: https://java.sun.com/people/gbracha.

Bracha stressed the generics specification’s conservative nature and its avoidance of major VM specification changes. As such, VM vendors won’t be forced to make major changes to every J2SE and J2ME VM in existence. This means that in the initial spec the VM will not track extra information in order to support generics. So, for example, if you call getClass() on the List<T>, you will get the List class, but you will not be able to determine that the Listis a List of Integers. Such an approach ensures that VM vendors can add support for generics quickly and easily. The specification also ensures backward compatibility so that old code can run unmodified on a VM that supports generics. This is critical, since the collection classes and thread classes will be rewritten to support generics.

However, Bracha did point out that the specification is extendable and that over time new features can and will be added. He even seemed amenable to a typedef-like mechanism to avoid long generic declarations. Time will tell what is and is not added.

Tony Sintesis a principal consultant at BroadVision. Tony, a
Sun-certified Java 1.1 programmer and Java 2 developer, has worked
with Java since 1997.

Source: www.infoworld.com