Generics were introduced in Java in Java 5.0 to allow type-safe generic programming. Unlike arrays, generic classes are neither covariant nor contravariant. For example, neither List
// a is a single-element List of String
List a = new ArrayList();
a.add("foo");
// b is a List of Object
List
b = a; // This is a compile-time error List
a.add("foo");
// b is a List of Object
List
However, generic type parameters can contain wildcards (a shortcut for an extra type parameter that is only used once). Example: Given a requirement for a method which operates on Lists, of any object, then the only operations that can be performed on the object are those for which the type relationships can be guaranteed to be safe.
// a is a single-element List of String
List a = new ArrayList();
a.add("foo");
// b is a List of anything
List b = a;
// retrieve the first element
Object c = b.get(0); // This is legal, because we can guarantee that the return type "?" is a subtype of Object
// Add an Integer to b.
b.add(new Integer (1)); // This is a compile-time error; we cannot guarantee that Integer is a subtype of the parameter type "?"
List
a.add("foo");
// b is a List of anything
List b = a;
// retrieve the first element
Object c = b.get(0); // This is legal, because we can guarantee that the return type "?" is a subtype of Object
// Add an Integer to b.
b.add(new Integer (1)); // This is a compile-time error; we cannot guarantee that Integer is a subtype of the parameter type "?"
Wildcards can also be bound, e.g. "? extends Foo" or "? super Foo" for upper and lower bounds, respectively. This allows to refine permitted performance. Example: given a List, then an element can be retrieved and safely assigned to a Foo type (contravariance). Given a List, then a Foo object can be safely added as an element (covariance).
0 comments:
Post a Comment