Java Generics

Generics let a class or a method take a type as a parameter, so one implementation serves every element type without casting and without copying. The compiler keeps track of the type argument, which is why a List<String> refuses an Integer at compile time instead of failing at run time.

This is the machinery behind the angle brackets you have already used: ArrayList<Integer>, Map<String, Double> and the Comparator<T> in the task scheduler project are all generic types. Writing one yourself is the step from using the library to extending it.

Classes that receive types as parameters are called "Generics". Type parameters provide a way for you to re-use the some code for different data types, just like a dynamic language. Using Generics we can relax the type system used by Java and improve code reusability without loosing performance.

Type Parameters

A generic class is recognized by the angle brackets that it uses to define type parameters also called sometimes type variables: T1, T2 ...Tn

 //generic class pattern
class GenericName <T1, T2, ... Tn?> {
  //generic class body
  .....
}
Observe the name of type variables is "Tn" but this is not necessary a class name nor a constant. In Java by convention type parameters are single uppercase letters: T, V, S, U, V, N, K, E. Do not get disturbed by this new convention. It is common for Java to have exceptions from general rules.

Type Arguments

A generic class can be invoked (used) in a declaration for making new objects. You must use operator "new" to create the object. Notice in the next pattern we use Integer as a type argument but could be another type.

 //using a generic type
GenericName<Integer> objectName = new  GenericName<Integer>();

Note: Type argument is the actual type we use for a type parameter to invoke the generic class. It does not have to be surrounded by double quotes. It is not a string but an actual type, recognized by the syntax color of your editor and thus by the compiler

A generic type is checked at compile time and erased at run time: the compiler records the type argument for its own analysis, then removes it, so List<String> and List<Integer> are the same class when the program runs. That is why new T[10] is illegal inside a generic class, and why generics work only with reference types — List<int> does not compile, and List<Integer> is how you ask for the same thing.