Tuesday, December 29, 2009

Generics

Generics can be compared with Class Templates in C++ programming. It is implemented to generalise the code for all data-types. That is, a single method definition can be used for different data-types and classes. Considering the following class, Box as an example for understanding Generics.
public class Box<T>{
   private T t; // T stands for "Type"

   public void add(T t){
      this.t = t;
   }
   public T get(){
      return t;
   }
}
The above generic class, Box, is used to store an object of a particular type, inside it. That is, an integer Box can store only an integer variable. Similarly, a String Box can store only a String object. The T in the class is replaced appropriately with a classname or type-name used in class instantiation.
Box integerBox = new Box();
Click here, to check out the non-generic version of the Box class.

Type Parameter Naming Conventions

By convention, type parameter names are single, uppercase letters. The most commonly used type parameter names are:
  • E - Element
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types


Generic Methods and Constructors

Let us understand this, with the help of a generic method definition inside the above generic class Box
public class Box<T>{
   .....
   .....
   .....

   public <U> void inspect(U u){
      System.out.println("T: " + t.getClass().getName());
      System.out.println("U: " + u.getClass().getName());
   }
}
Now, let the class be instantiated, as an Integer type. If we invoke the method, with the following line of code:
inspect("some text");
then the output is:
T: java.lang.Integer
U: java.lang.String

Bounded Type Parameters


The extent of generality imposed on a class or a method can be restricted to some classes or types. This is achieved with the help of extends keyword. Suppose, if you want a method to be used only with instances of Number class, then, the method can be defined as:
public <U extends Number> void inspect(U u){
   ..........
}
This method can now be invoked by an object of Number class or its sub-classes. To specify additional interfaces that must be implemented, used '&' character.

Wildcards

In JAVA, unknown types can also be represented in Generics with the help of wildcard character "?". Unknown types, with either upperbound or lowerbound can be specified as follows:
Cage<? extends Animal> someCage = ...; // here Animal class is the upperbound
Cage<? super Animal> someCage = ...; // here Animal class is the lowerbound
Now consider, Lion and Butterfly to be subtypes of Animal. If, Cage<Animal> is defined as a cage to hold all animals, then Cage<Lion> is for lions and Cage is for butterflies. Now, if we see logically, it appears that Cage and Cage<butterfly> are subtypes of Cage<Animal>, but reality Cage<Lion>, Cage<Butterfly> and Cage<Animal> are all subtypes of Cage<? extends Animal>. This is because, Cage<Animal> is not a generic class, but infact a specification of generic class Cage<? extends Animal>. Click here, to understand wildcards more clearly.

Unbounded Wildcards are just defined with '<?>'

Type Erasure

Some of the operations given below are not possible with Generic classes:
  • if(item instanceof E)
  • E item2 = new E();
  • E[] iArray = new E[10];
  • E obj = [E]new Object();
This is because, when a generic type is instantiated, the compiler removes all information related to type parameters and type arguments within a class or method. Hence, any operation that includes knowing the type or modifying the type cannot be performed. This process of removing the type information is called, Type Erasure.

tutorials
subtyping


Reference Links:
C++ Class Templates

No comments:

Post a Comment