Tuesday, 21 September 2010

Generics in java

Using predefined generic classes is commmon, writing them is less common.
Generics are primarily a way for library authors to write something once, which users can customize to their own types. You generally won't define generic classes and methods yourself, but you do have to understand how and why they are used.

Basic problem - restricted types or completely open

When you want to write something that works well with objects from many classes or interfaces as parameters, you have a problem. When you choose a type T, then only objects of that type or subclass can be used.
This is ok, but if you want something general, you often have to go all the way up the inheritance hierarchy to Object, which works for all types, so it is completely generalized. This is how the Java Collections were written before Java 5 - they often used Object as the type of their parameters. This was very convenient for the implementors, but less useful to the users.

Restricting the type : For most data structures, there is only one type that really should be used, for example, you have an ArrayList of Strings, or an ArrayList of Dates, but you rarely mix them. Indeed it is often considered very bad style to mix them. However, library methods that work with Object allow the use to mistakenly add different types.
Example comparing the legacy with generic style
// Typical Collections usage before Java 5
List greetings = new ArrayList();
greetings.add("We come in peace.");
greetings.add("Take me to your leader.");
greetings.add("Resistance is futile.");

Iterator it = greetings.iterator();
while (it.hasNext()) {
String aGreeting = (String)it.next();
attemptCommunication(aGreeting);
}

Same example using generics

// Same example using generics.
List<String> greetings = new ArrayList<String>();
greetings.add("We come in peace.");
greetings.add("Take me to your leader.");
greetings.add("Resistance is futile.");

Iterator it = greetings.iterator();
while (it.hasNext()) {
String aGreeting = it.next(); // No downcast.
attemptCommunication(aGreeting);
}

Also refer (you can skip it if you understood here only ) -See more on dealing with casting through generics

Specifying the type of element in the collection has nice consequences:
  • Trying to add something of the wrong type gives a compile-timer error.
  • Getting elements doesn't require an explicit downcast, although this example doesn't show how often this is convenient.
  • Specifying the type provides a lot of documentation.

Type parameter naming - T, U, ...

Altho any names are possible for type parameters, they are traditionally written in upper case and often taken from the sequence T, U, V, ... Other upper case letters are used when they have specific meanings, eg, K for the type of a key, E for element type.

Where you can't use generic types in defining a generic class/method

Generic types, altho they have solved some problems, also have some limitations, not all of which are entirely obvious.
  • You can't create objects of type T.
  • You can't create arrays of type T, altho you can create new Collections data structures.
  • Don't use them for statics.

    No comments:

    Post a Comment