Generics are somewhat similar to Templates in C++ and were added to Java in 2004 as part of J2SE 5.0 to add more compile-time type-safety.
Example:
public class Box<T> {
private T t; // T stands for "Type"
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public <W extends Number & MyInterface> void inspect(W w){
System.out.println("T: " + t.getClass().getName());
System.out.println("W: " + w.getClass().getName());
}
}
The above is used as:
Box<Integer>integerBox;
So, in the above, T is
a Generic and so is W. W has further restrictions imposed on it such that it can only be
passed as classes/interfaces that are derived from Number and MyInterface
Type-Erasure
Note that generics provide compile-time safety only.
The type-information is removed after compilation so that it's not available during run-time.
This is called type-erasure.
Due to type-erasure, the following code will print true.
HashMap<String, String> strMap = new HashMap<String, String>();
HashMap<Integer, Integer> intMap = new HashMap<Integer, Integer>();
System.out.println (intMap.getClass() == strMap.getClass())
Due to this, Java generics differ from C++ templates.
In Java, the runtime does not generate a different class for each variation of generic as the information is not available at that time.
Due to this absence of runtime knowledge, following constructs are not possible in Java:
1) new T (); // does not compile because it knows that type information is absent at runtime.
2) MyException<T> extends Exception; // does not compile because if user writes two catch blocks with different parameters for same try, Java does not know which catch to execute.
Got a thought to share or found a bug in the code? We'd love to hear from you: