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.
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
.....
}
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.