The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.
SeeDev.java for updated tutorials taking advantage of the latest releases.
SeeJava Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.
SeeJDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.
Ageneric type is a generic class or interface that is parameterized over types. The followingBox class will be modified to demonstrate the concept.
Begin by examining a non-genericBox class that operates on objects of any type. It needs only to provide two methods:set, which adds an object to the box, andget, which retrieves it:
public class Box { private Object object; public void set(Object object) { this.object = object; } public Object get() { return object; }}
Since its methods accept or return anObject, you are free to pass in whatever you want, provided that it is not one of the primitive types. There is no way to verify, at compile time, how the class is used. One part of the code may place anInteger in the box and expect to getIntegers out of it, while another part of the code may mistakenly pass in aString, resulting in a runtime error.
Ageneric class is defined with the following format:
class name<T1, T2, ..., Tn> { /* ... */ }
The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies thetype parameters (also calledtype variables)T1,T2, ..., andTn.
To update theBox class to use generics, you create ageneric type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable,T, that can be used anywhere inside the class.
With this change, theBox class becomes:
/** * Generic version of the Box class. * @param <T> the type of the value being boxed */public class Box<T> { // T stands for "Type" private T t; public void set(T t) { this.t = t; } public T get() { return t; }}
As you can see, all occurrences ofObject are replaced byT. A type variable can be anynon-primitive type you specify: any class type, any interface type, any array type, or even another type variable.
This same technique can be applied to create generic interfaces.
By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variablenaming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.
The most commonly used type parameter names are:
You'll see these names used throughout the Java SE API and the rest of this lesson.
To reference the genericBox class from within your code, you must perform ageneric type invocation, which replacesT with some concrete value, such asInteger:
Box<Integer> integerBox;
You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you are passing atype argument —Integer in this case — to theBox class itself.
Like any other variable declaration, this code does not actually create a newBox object. It simply declares thatintegerBox will hold a reference to a "Box ofInteger", which is howBox<Integer> is read.
An invocation of a generic type is generally known as aparameterized type.
To instantiate this class, use thenew keyword, as usual, but place<Integer> between the class name and the parenthesis:
Box<Integer> integerBox = new Box<Integer>();
In Java SE 7 and later, you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<>) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally calledthe diamond. For example, you can create an instance ofBox<Integer> with the following statement:
Box<Integer> integerBox = new Box<>();
For more information on diamond notation and type inference, seeType Inference.
As mentioned previously, a generic class can have multiple type parameters. For example, the genericOrderedPair class, which implements the genericPair interface:
public interface Pair<K, V> { public K getKey(); public V getValue();}public class OrderedPair<K, V> implements Pair<K, V> { private K key; private V value; public OrderedPair(K key, V value) {this.key = key;this.value = value; } public K getKey(){ return key; } public V getValue() { return value; }}
The following statements create two instantiations of theOrderedPair class:
Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);Pair<String, String> p2 = new OrderedPair<String, String>("hello", "world");
The code,new OrderedPair<String, Integer>, instantiatesK as aString andV as anInteger. Therefore, the parameter types ofOrderedPair's constructor areString andInteger, respectively. Due toautoboxing, it is valid to pass aString and anint to the class.
As mentioned inThe Diamond, because a Java compiler can infer theK andV types from the declarationOrderedPair<String, Integer>, these statements can be shortened using diamond notation:
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");
To create a generic interface, follow the same conventions as for creating a generic class.
You can also substitute a type parameter (that is,K orV) with a parameterized type (that is,List<String>). For example, using theOrderedPair<K, V> example:
OrderedPair<String,Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));
About Oracle |Contact Us |Legal Notices |Terms of Use |Your Privacy Rights
Copyright © 1995, 2024 Oracle and/or its affiliates. All rights reserved.