- introduced in J2SE 5.0
- adds robustness/stability on code by making more bugs detectable at compile time
- normal way can cause runtime ClassCastException
public class Box { private Object object; public void add(Object object) { this.object = object; } public Object get() { return object; } } Box integerBox = new Box(); integerBox.add("10"); // note how the type is now String Integer someInteger = (Integer)integerBox.get();
- sample generic version with type variable T
public class Box
{ private T t; // T stands for "Type" public void add(T t) { this.t = t; } public T get() { return t; } } Box integerBox = new Box (); integerBox.add(new Integer(10)); Integer someInteger = integerBox.get(); // no cast! - generic method/constructor
public static <U> void fillBoxes(U u, List<Box<U>> boxes) { for (Box<U> box : boxes) { box.add(u); } } Crayon red = ...; List<Box<Crayon>> crayonBoxes = ...; // normal way Box.<Crayon>fillBoxes(red, crayonBoxes); // with type inference Box.fillBoxes(red, crayonBoxes); // compiler infers that U is Crayon
- Bounded Parameter types -> when variables are restricted to certain types, upper bound only
<U extends Number & MyInterface> // uses extend for both classes & interfaces
- Unknown type/wilcard bounds -> represented by wildcard character "?"
3 different flavors of wildcards:- " ? " - the unbounded wildcard. It stands for the family of all types.
- " ? extends Type " - a wildcard with an upper bound. It stands for the family of all types that are subtypes of Type , type Type being included.
- " ? super Type " - a wildcard with a lower bound. It stands for the family of all types that are supertypes of Type , type Type being included.
// Box<Integer> and Box<Double> are not subtypes of Box<Number> Box<Number> box = new Box<Integer>(); // compile-time error // Box<Integer> and Box<Double> are subtypes of Box<? extends Number> Box<? extends Number> box = new Box<Integer>(); // ok Integer i = new Integer(1); Number n = i; // compile-time error // Integer is not '? extends Number' // we are not sure that the instance type of Box is Integer, so we cannot add i box.add(i); // compile-time error // Number is not '? extends Number' // we are sure that the type of Box extends a Number but we are not sure of the // instance type of n, so we cannot add n // what if runtime type of Box is Box<Double> but n is Integer box.add(n) // compile-time error // we are not sure that the type of Box is an Integer Integer i2 = box.get(); // we are sure that the type of Box is always extends a Number Number n2 = box.get(); // ok // sample using upperbound & lowerbound wildcards public class Collections { public static <T> void copy ( List<? super T> dest, List<? extends T> src) { // bounded wildcard parameterized types for (int i=0; i<src.size(); i++) dest.set(i,src.get(i)); } }
- Type Erasure -> when generic types are instantiated, all generic information are removed leaving only the raw type. Box
becomes Box only. public class MyClass
{ public static void myMethod(Object item) { if (item instanceof E) { //Compiler error ... } E item2 = new E(); //Compiler error E[] iArray = new E[10]; //Compiler error E obj = (E)new Object(); //Unchecked cast warning } }
Sources:
http://java.sun.com/docs/books/tutorial/java/generics/index.html
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
No comments:
Post a Comment