Mar 12 / Leandro De Brasi

Java Generics

Generics are a facility of generic programming that was added to the Java programming language in 2004 as part of Java 5.

The feature of Generics in Java allows applications to create classes and objects that can operate on any defined types. Programmers can now make use of the generics feature for a much better code. There is no need for un-necessary casting when dealing with Objects in a Collection.

Generics make a Java program well formed – enabling the compiler to perform enough type checks based on the static type information provided and to avoid unexpected type errors that could occur at runtime.

Then we will see in a simple example, as generics enriches our code.

Java before generics:

1
2
3
4
List dictionary = new ArrayList();
dictionary.add("A");
dictionary.add("B");
String s = ((String)dictionary.get(0) + (String)dictionary.get(1));

Java with generics:

1
2
3
4
List<string> dictionary = new ArrayList<string>();
dictionary.add("A");
dictionary.add("B");
String s = dictionary.get(0) + dictionary.get(1);

Without generics, the type parameters are omitted, but you must explicitly cast whenever an element is extracted from list.

Generic Class

In a generic class, type parameters(T and U) appear in the header that declares the class, but not in the constructor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Pair<t, U> {
	private final T first;
	private final U second;
	public Pair(T first, U second) {
		this.first = first;
		this.second = second;
	}
	public T getFirst() {
		return first;
	}
	public U getSecond() {
		return second;
	}
}

However, actual type parameters are passed to the constructor whenever it is invoked:

1
2
3
Pair<string, Integer> pair = new Pair<string, Integer>("one", 2);
String s = pair.getFirst();
Integer i = pair.getSecond();

Generic Methods

Here is a method that accepts an array of any type and converts it to a list:

1
2
3
4
5
6
7
public class ListUtil {
	public static <t> List<t> toList(T[] arr) {
		List<t> list = new ArrayList<t>();
		for (T element : arr) list.add(element);
		return list;
	}
}

The static method toList convert an array of type T[] on list of type List<T>. The method may be invoking as fallows:

1
2
List<integer> ints = ListUtil.toList(new Integer[] {1, 2, 3});
List<string> dictionary = ListUtil.toList(new String[] {"A", "B", "C"});

Wildcards

Sometimes we would like lists to behave more like arrays, in that we want to accept not only a list with elements of a given type, but also a list with elements of any subtype of a given type. For this purpose, we use wildcards.

To specify the upper bound of a generic element, the extends keyword is used, which indicates that the generic type is a subtype of the bounding class. Thus it must either extend the class, or implement the interface of the bounding class. So List<? extends Number> means that the given list contains objects of some unknown type which extends the Number class. For example, the list could be List<Float>, List<Integer> or List<Number>.

To specify the lower bound of a generic element, the super keyword is used, which indicates that the generic type is a supertype of the bounding class. So List<? super Number> could be List<Number> or List<Object>. Reading from the list returns objects of type Object. Any element of type Number can be added to the list, since it is guaranteed to be a valid type to store in the list.

1
2
3
4
5
public interface Collection<e> {
	...
	public boolean addAll(Collection<? extends E> c);
	...
}

In the example, we create an empty list of numbers, and add to it first a list of integers and then a list of doubles:

1
2
3
4
5
List<number> nums = new ArrayList<number>();
List<integer> ints = Arrays.asList(1, 2);
List<double> dbls = Arrays.asList(4.64, 8.11);
nums.addAll(ints);
nums.addAll(dbls);

Multiple Bounds

In rare situations, it may be desirable to have multiple bounds, and we show how to do so here.
In the next example, we use three interfaces: Human, Martian and Speaker.

1
2
3
4
5
6
...
public static <s extends Human & Speaker,
			T extends Martian & Speaker>
	void transform(S hs, T ms)
{
...

3 Comments

leave a comment
  1. ivan / Nov 24 2008

    Interezante el articulo
    Gracias

  2. Coss / Jan 17 2009

    Buen articulo

  3. Fred / Nov 17 2009

    Muy bueno el articulo

Leave a Comment

Security Code: