Previously we saw how generics can help make our code more manageable and flexible to future needs. We created the following generic class:
public class Box <T> { private T data; public Box(T data) { this.data = data; } public T getData() { return this.data; } }
In the example above notice that:
- The type parameter must be specified within the diamond operator (
<>
) after theclass
name. - The type parameter,
T
, is similar to a method parameter but instead receives aclass
orinterface
type as an argument as opposed to reference or primitive type. - The constructor has a
T
type parameter when wanting to alterdata
. - The getter returns the type parameter
T
when returningdata
.
Creating generic classes is great but we also need to be able to create references to them in our programs:
Box<String> myStringBox = new Box<>("Apple");
In the example above, we can see the reference myStringBox
is created similarly to non-generic references but differ in:
- Needing the diamond operator with the
class
orinterface
type argument,<String>
in this example, after theclass
name. - Needing the empty diamond operator prior to calling the constructor,
new Box<>("Apple")
.
When defining type parameters, although not being a hard requirement, it’s best practice to make them single, uppercase letters to easily distinguish them from the names of classes or variables. By convention common type parameters include E
(Elements), K
(Key), N
(Number), T
(Type), V
(Value), and S
(or U
or V
) for multiple type parameters.
One final thing to note is that prior to Java 7, generic references needed to be created like:
Box<String> myStringBox = new Box<String>("Apple");
In the example above, the <String>
type argument also needed to be specified prior to calling the constructor. This is no longer necessary due to Java’s type inference where the compiler can infer the <String>
type argument in the constructor from the context of the reference definition Box<String>
.
Let’s practice creating a generic class and creating an instance of it.
Instructions
Let’s start by defining our generic class that will represent a real world container.
In Container.java, create a generic class Container
with a type paramter T
and create a type T
field named data
.
Note: It’s okay to see an error in the terminal window about a missing main()
method.
Let’s complete our class so we can create references to it.
In the Container
class, add a public
constructor with a type T
parameter named data
. Set the data
field to the value of the data
parameter. Also, create a getter named getData()
and a setter named setData()
for the data
field.
Note: It’s okay to see an error in the terminal window about a missing main()
method.
Let’s create Container
references and print it’s data
field to the terminal.
We’ve provided a Book
class for you to use with a single String
argument constructor. In main()
of Main.java, create the following references:
- A
String
typeContainer
namedwordContainer
. UsemyWord
to initialize it. - A
Book
typeContainer
namedbookContainer
. UsemyBook
to initialize it.
Call System.out.println()
to print wordContainer
s data
field using it’s getter.
Call System.out.println()
to print bookContainer
s data
field using it’s getter.