Articles Related
Why ?
Generics allow to abstract over types and add the following two advanatges- Stronger type checks at compile time. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find. The compiler can check the type correctness of the program at compile-time.
- Elimination of cast.
List myIntList = new LinkedList(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = (Integer) myIntList.iterator().next(); // 3
Becomes with generic:
List<Integer> myIntList = new LinkedList<Integer>(); // 1' Not only a List, but a List of Integer,
myIntList.add(new Integer(0)); // 2'
Integer x = myIntList.iterator().next(); // 3' -- Cast is gone
Example
The most common examples are container types, such as those in the Collections hierarchy.- A Set has a single type parameter, representing its element type;
- a Map has two, representing its key and value types
Type Variable
Type variables don't exist at run time. See type_erasureParameter
The T in Foois a type parameter Type parameter names are single, uppercase letters. The most commonly used type parameter names are:- E - Element (used extensively by the Java Collections Framework)
- K - Key
- N - Number
- T - Type
- V - Value
- S,U,V etc. - 2nd, 3rd, 4th types
Bounded
A method that operates on numbers that only want to accept instances of Number or its subclasses will used bounded type parameters.Argument
String in Foof is a type argument.
==== Wildcard ====
The question mark (?), called the wildcard, represents an unknown type.
The wildcard is never used as a type argument for:
* a generic method invocation,
* a generic class instance creation,
* or a supertype.
Others:
* upper bounded wildcards,
public static void process(List<? extends Foo> list) { /* … */ }
* lower bounded wildcards,
public static void addNumbers(List<? super Integer> list) { /* … */ }
* unbounded wildcards
public static void printList(List<?> list) { /* … */ }
* and wildcard capture (when the compiler infers a particular type from the code)
==== Question mark (?) ====
See wildcard
===== Subtyping =====
Java - (Inheritance|Class Hierarchy) - (Subclass|Superclass) - (Extends, Super) - ( is a relationship)
Definition of a custom list interface, PayloadList, that associates an optional value of generic type P with each element. interface PayloadListextends List{void setPayload(int index, P val);…}Parameterized typeWhen you declare or instantiate a generic type with actual type arguments, you have a parameterized type. RuntimeComes from Collections#checkedCollectionThe generics mechanism in the language provides compile-time (static) type checking, but it is possible to defeat this mechanism with unchecked casts. Usually this is not a problem, as the compiler issues warnings on all such unchecked operations. There are, however, times when static type checking alone is not sufficient. For example, suppose a collection is passed to a third-party library and it is imperative that the library code not corrupt the collection by inserting an element of the wrong type. Type erasureGenerics are [[code:type:type_checking|type correctness]] at compile-time. The generic type information is then removed in a process called type erasure.Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.Type variables don't exist at run time. This means that they entail no performance overhead in either time nor space, which is nice. Unfortunately, it also means that you can't reliably use them in casts and instanceOf.Example, List will be become a non-generic type List'' (A list that contains objects).UnboundedWhen the type parameter T is unbounded, the Java compiler replaces it with Object:
public class Node<T> {
private T data;
private Node<T> next;
/*....*/
}
becomes
public class Node {
private Object data;
private Node next;
/*....*/
}
BoundedThe Java compiler replaces the bounded type parameter T with the first bound class (ie Comparable):
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
/*....*/
}
becomes
public class Node {
private Comparable data;
private Node next;
/*....*/
}
CastIndirectly through an intermediate wildcard typeYou can't cast a generic type of one parameter to another. However, since you can cast to and from wildcard types, you can cast through an intermediate wildcard type.
List<B> variable = (List<B>)(List<?>) collectionOfListA;
Casts and InstanceOfCannot Use Casts or instanceof with Parameterized TypesBecause the Java compiler erases all type parameters in generic code, you cannot verify which parameterized type for a generic type is being used at runtime:
public static <E> void rtti(List<E> list) {
if (list instanceof ArrayList<Integer>) { // compile-time error
// ...
}
}
The runtime does not keep track of type parameters, so it cannot tell the difference between an ArrayListand an ArrayList. The most you can do is to use an unbounded wildcard to verify that the list is an ArrayList:
public static void rtti(List<?> list) {
if (list instanceof ArrayList<?>) { // OK; instanceof requires a reifiable type
// ...
}
}
Documentation / Reference
-
-