Java Generics

Category: 

Generics are a facility of generic programming that were added to Java within version 5. The core idea behind these parameterized types is the addition of so called Type Variables. They allow a type or method to operate on objects of various types, while providing compile-time safety.

Why Generics?

The best way to show the benefit of generics is a simple example with and without generics. First let's look at the code without generics.

//we want a list of Points
ArrayList points = new ArrayList();
list.add(new Point(1,2));
list.add("Hello World"); // An Arraylist holds any Object, so this is a correct statement

Point p1 = (Point)points.get(0);
Point p2 = (Point)points.get(1); // Runtime Error

We want to have a list of Points, but we need an explicit typecast to get the points back, because the ArrayList only saves the baseclass Object. Furthermore we get a runtime error, because we tried to cast a String to a Point. As you see this example is very error prone.

ArrayList<Point> points = new ArrayList<Point>();
list.add(new Point(1,2));
list.add("Hello World"); // the compiler tells us, that this is wrong

Point p1 = points.get(0);
Point p2 = points.get(1);

Thanks to the generics we don't need a typecast. Additionally we see errors directly at compile time.

Generics usage

To extend a class or an interface with a type parameter, we only need to add this in angle brackets after the class name. In the class we can use this type variable as any other type. The following snippet shows a short example.

public class Test<T> {
  private T var;
  public T get() { return var; }
  public void set(T t) { this.var = t; }
}

We can replace the type variable T with any real type:
[JAVA]
Test test = new Test();
test.set("Hello");
[/JAVA]

Type restrictions

Sometimes we don't want to allow any type. Maybe we only want to allow types that implements the Comparable interface, because we want to implement an ordered list. For this purpose we can restrict the type variable with the extends keyword.

class SortedList<T extends Comparable<T>> {
  //...
}

You can add as many restrictions as you like. This is done via the &-operator. Let's assume we want to make our list iterable:

class SortedList<T extends Comparable<T> & Iterable<T>> {
  //...
}

Until now we only restrict our types to special class and it's subclasses. We can do it the otherway round, we can restrict the generic to be a class or one of it's superclasses. For this we use the super keyword and the wildcard operator '?'.

ArrayList<? super Integer> list = new ArrayList<Number>();