Chapter 17 Generics • This is related to the ArrayList class. • An ArrayList can store different types of data in the same data structure. • When you get information out of the array, using the get() method, you have to cast to the appropriate type. • If you cast to the wrong type, the compiler can't catch that at compile time, and you can get runtime errors as a result. Generics avoids this. ArrayList • Used like an array, but it automatically grows to accept new values. • Some important methods: – add(Object myObject) – get(int myIndex) – size() – toString() – remove(int toRemove) – add(int addWhere, Object myObject) To use a generic type with ArrayList • ArrayList<Rect> myRect = new Arraylist<Rect>(); • myRect.add(SomeRectangle); • … • arect = myRect.get(0); Creating a Generic Class • public class Point<T> { private T xCoordinate; private T yCoordinate; public Point(T x, T y) { xCoordinate = x; yCoordinate = y; } } Only classes as types • You can't use int and double, you have to use Integer and Double. • Constants get "autoboxed" into their correct types. • Point<Double> = new Point<Double>(1,2.5); • You can (but shouldn't) instantiate without specifying a Type argument. Commonly Used Parameter Names • T for a general type • S for a general type, when T already used • E to represent the type of an element, as in an element of an ArrayList • K to represent the type of a key in a class that keeps key/value pairs. • V to represent the type of a value in a class that keeps key/value pairs. Objects of Generic Class to a Method • public static void printPoint(Point<Integer> point) { … } • this could print a point with Integer coordinates, but what about a point with Double coordinates? • Number class tempting, but won't work • public static void printPoint(Point<?> point) { … } • public static void printPoint(Point<?> extends Number> point) { … } • This limits the types of classes. – Point<String> sP = new Point<String>("1","2"); – printPoint(sP); //Error! Type Parameter in Method Header • public static <T extends Number> void PrintPoint(Point<T> myPoint); • The extends keyword constrains type to an Upper Bound – <T extends Number> constrains T to any type in the hierarchy below number (int, double, …) • The super keyword constrains type to an LowerBound – <? super Integer> as a parameter's type constrains it to a lower bound: there are only two: Number and Object. – Such a parameter could only be Integer, Number, or Object. Writing generic methods • public static <E> void displayArray(E[] array){ for (E element: array) { System.out.println(element); } } Constraining a Type Parameter • public class Point<T extends Number> { private T xC; private T yC; public Point(T x, T y) { //Constructor xC = x; yC = y; } public void setX(T x) { xC = x; } …. Inheritance and Generics • A generic class can be a superclass, and it can extend other classes. • public class Point3D<T extends Number> extends Point<T> { T cZ; public Point3D(T x, T y, T z) { super(x,y); cZ = z; } public T getZ() { return cZ; } public void setZ(T z) { cZ = z; } } More Generic topics • Multiple type parameters –You can put a list of type parameters in "<",">" after the class name in the class declaration: public class pair<T, S> { –(See TwoTypeParams project) Generics and interfaces • public interface Comparable<T> { int compareTo(T o); } • Suppose we are writing a (non-generic) class Tree that can compare trees. We might write: public class Tree implements Comparable<Tree> { public int compareTo(Tree o) { return …. } } Constraining a type parameter • public class LuxuryCar implements Comparable<LuxuryCar> { … } public static <T extends Comparable<T> > T greatest(T arg1, T arg2) { if (arg1.compareTo(arg2) > 0) return arg1; else return arg2; } • What does " <T extends Comparable<T> > " mean? The type passed to T must implement the Comparable interface. Erasure • When the Java compiler processes a generic class or method, it erases the generic notation and substitutes an actual type for each parameter. • It looks like type variables are essentially replaced with Object, except that compile-time type checking is enabled. • Generic notation exists only in the source code. Once the compiler confirms that a generic type is being used safely, it converts it into a raw type, which is simply a non-generic type. At the bytecode level, only raw types exist. • Cast operators will be inserted when necessary. Restrictions on the use of generic types • You cannot create an instance of a type parameter • public class MyClass<T> { public MyClass() { // constructor T myObject = new T(); // causes error } } More restrictions • You cannot create an array of generic class objects. This will fail: ArrayList<String>[] a = new ArrayList<String>[100]; • A generic's class type parameter cannot be the type of a static field, and cannot be referred to in a static method. • You cannot make an exception type generic.