Generics
In this section, we study Java Generics.
Introduction to Generics
Writing a Generic Class
Autoboxing and Unboxing
Instantiating a Generic Class without Specifying a Type Argument
Commonly Used Type Parameters
Introduction to Generics
A generic class or method is one whose definition uses a placeholder for one or more of the types it works with.The placeholder is really a type parameter.
For a generic class, the actual type argument is specified when an object of the generic class is being instantiated.
For a generic method, the compiler deduces the actual type argument from the type of data being passed to the method.
Using the Diamond Operator for Type Inference
The ArrayList class is generic: the definition of the class uses a type parameter for the type of the elements that will be stored.
ArrayList<String> specifies a version of the generic ArrayList class that can hold String elements only.
ArrayList<Integer> specifies a version of the generic ArrayList class that can hold Integer elements only.
Instantiation and Use of a Generic Class:
ArrayList<String> myList = new ArrayList<String>();
myList.add(“Java is fun”);
String str = myList.get(0);
myList.add(“Java is fun”);
String str = myList.get(0);
Writing Generic Class
Generic Point Class:Consider a “point” as a pair of coordinates x and y, where x and y can be any type.
The type of x must always be the same as the type of y.
public class Point<T> {
private T xCoordinate; // The X coordinate
private T yCoordinate; // The Y coordinate
public Point(T x, T y) {
xCoordinate = x;
yCoordinate = y;
}
...
}
// Create various Point objects in the client program
Point<Integer> iPoint = new Point<>(1, 2);
Point<Double> dPoint = new Point<>(1.5, 2.5);
private T xCoordinate; // The X coordinate
private T yCoordinate; // The Y coordinate
public Point(T x, T y) {
xCoordinate = x;
yCoordinate = y;
}
...
}
// Create various Point objects in the client program
Point<Integer> iPoint = new Point<>(1, 2);
Point<Double> dPoint = new Point<>(1.5, 2.5);
Only Reference Types Can Be Passed to Type Parameters
Only reference types can be used to declare or instantiate a generic class.
ArrayList<Integer> myIntList = new ArrayList<Integer>; // OK
ArrayList<int>myIntList = new ArrayList<int>; // Error
ArrayList<int>myIntList = new ArrayList<int>; // Error
int is not a reference type, so it cannot be used to declare or instantiate a generic class.
The corresponding wrapper class must be used to instantiate a generic class with a primitive type argument.
Autoboxing and Unboxing
Autoboxing is the automatic conversion of a primitive type to the corresponding wrapper type when it is used in a context where a reference type is required.
Integer intObj = 35; // Autoboxing converts int to Integer
Point<Number> nPoint = new Point<Number>(3.14, 2.71); // double to Number
Point<Number> nPoint = new Point<Number>(3.14, 2.71); // double to Number
Unboxing is the automatic unwrapping of a wrapper type to give the corresponding primitive type when the wrapper type is used in a context that requires a primitive type.
int i = new Integer(34); // Unboxing converts Integer to int
Point<Double> p = new Point<Double>(3.14, 2.71); // doubles 3.14, 2.71 to Double
double x = p.getX(); // p.getX() returns Double which is unboxed to double
Point<Double> p = new Point<Double>(3.14, 2.71); // doubles 3.14, 2.71 to Double
double x = p.getX(); // p.getX() returns Double which is unboxed to double
Instantiating a Generic Class without Specifying a Type Argument
It is possible, but not recommended.Raw Types
You can create an instance of a generic class without specifying the actual type argument.
An object created in this manner is said to be of a raw type.
Point rawPoint = new Point("Anna", new Integer(26));
System.out.println(rawPoint);
//Output: (Anna, 26)
System.out.println(rawPoint);
//Output: (Anna, 26)
Raw Types and Casting
The Object type is used for unspecified types in raw types.
When using raw types, it is necessary for the programmer to keep track of types used and use casting:
Point rawPoint = new Point("Anna", new Integer(26));
System.out.println(rawPoint);
String name = (String)rawPoint.getX(); // Cast is needed
int age = (Integer)rawPoint.getY(); // Cast is needed
System.out.println(name);
System.out.println(age);
System.out.println(rawPoint);
String name = (String)rawPoint.getX(); // Cast is needed
int age = (Integer)rawPoint.getY(); // Cast is needed
System.out.println(name);
System.out.println(age);
Commonly Used Type Parameters
Name | Meaning |
---|---|
T | A generic type |
S | A generic type |
E | A genetic type of an element in a collection |
K | A generic type of a key for a collection that maintains key/value pairs |
V | A generic type of a value for a collection that maintains key/value pairs |