Java Generics – An Introduction

Java introduced generics in its Tiger release (5.0). It has been around for some time now. I was trying to understand the nittygritties of the feature when I came around an exhaustive text on generics by Angelika Langer. Although extremely exhaustive I would prefer a shorter version for my personal understanding. So here goes…..

One of the most popularly used features of the Java programming language is its Collections framework. However before Java 5 the Collections framework was hampered by a serious limitation. It did not provide the developer the ability to define the runtime type for a particular collection. Consider a requirement that a developer needs to hold a collection of strings. The collection class say ArrayList or Vector does not provide an ability to ensure that all objects added to the collection are of type String. This lead to poliferation of new user defined classes to ensure runtime type validation. Finally Java in its Tiger release provided a solution to this problem via the generics feature.

So how do you use generics. Here’s how you define a collection before Java 5.

<pre>List dogs = new ArrayList();

I want to ensure that the dogs list holds only Dog object. Here’s how you achieve the same via generics.

List<Dog> dogs = new ArrayList<Dog>();

The dogs list is now limited to acting as a container for Dog object instances and this is validated at runtime thus providing the elusive type safety checks. Now let’s play around with this feature.

//Package and import declarations have been removed for abbrevity.
public class Generics1Test {

    public static void main(String[] args) {
        List<Dog> dogs = new ArrayList<Dog>();

        Dog dog = new Dog();
        dogs.add(dog);

        Cat cat = new Cat();
       dogs.add(cat);
    }
}

class Animal {
}

class Dog extends Animal {
}

class Cat extends Animal {
}

Line 11 does not compile. Eclipse throws the following compilation error message:

The method add(Dog) in the type List<Dog> is not applicable for the arguments (Cat)

Let’s change the list a bit and make it contain animals instead of just dogs.
The list declaration of line 5 is changed to the following:

    List<Animal> dogs = new ArrayList<Animal>();

Line 11 compiles without any errors.

Now let’s try some variations in the generic collection assignment.

public class Generics3Test {

    public static void main(String[] args) {

        List<Dog> dogs = new ArrayList<Dog>();
        Collection<Dog> dogCollection = new ArrayList<Dog>();
        List<Animal> animals = new ArrayList<Animal>();

        Dog dog1 = new Dog();
        Dog dog2 = new Dog();
        Cat cat1 = new Cat();

        dogs.add(dog1);
        dogs.add(dog2);

        animals.add(dog1);
        animals.add(dog2);
        animals.add(cat1);

        dogCollection = dogs;
        Dog dog3 = new Dog(); 
        dogCollection.add(dog3);
       //animals = dogs;
    }

}

Upto line 18 we have not done anything out of the box. Line 20 does something special. It says that we can assign Collection<Dog> reference to List<Dog>. This means that as long as the generics paramater type (Dog) remains unchanged the raw type Collection can support its inheritance relationship. However vice-a-versa line 23 is not allowed. The following compilation error messages is thrown.

Type mismatch: cannot convert from List<Dog> to List<Animal>

For a better understanding of why this happens refer the following link.

All the examples above used generic types made available as a part of the Java 5 release. It is also possible for us to define custom generic type. Here’s the sample:

public class KeyValuePair <K, V>{
    private K key = null;
    private V value = null;
    public KeyValuePair(K k, V v) {
        this.key = k;
        this.value = v;
    }
    public K getKey() {
        return this.key;
    }
    public V getValue() {
        return this.value;
    }
    public void setValue(V val) {
        this.value = val
    }
}

Here’s a sample test client:

public class Generics4Test {
     public static void main(String[] args) {
          System.out.println("KEY: " + pair.getKey());
          System.out.println("VALUE: " + pair.getValue());
          pair.setValue(Long.valueOf(199));
KeyValuePair<String, Long> pair = new KeyValuePair<String, Long>("ONE", Long.valueOf(1));
          System.out.println("VALUE: " + pair.getValue());
    }
}

The output generated is

KEY: ONE
VALUE: 1
VALUE: 199
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s