Generic Interfaces
Generic types also include generic interfaces, which are declared analogous to generic classes. The specification of formal type parameters in a generic interface is the same as in a generic class. Example 11.3 declares a generic interface that defines the reference type IMonoLink<E> for objects that store a data value of type E.
Example 11.3 A Generic Interface and Its Implementation
interface IMonoLink<E> {
void setData(E data);
E getData();
void setNext(IMonoLink<E> next);
IMonoLink<E> getNext();
}
class MonoNode<E> implements IMonoLink<E> {
private E data; // Data
private IMonoLink<E> next; // Reference to next node (1)
MonoNode(E data, IMonoLink<E> next) { // (2)
this.data = data;
this.next = next;
}
@Override public void setData(E data) { this.data = data; }
@Override public E getData() { return this.data; }
@Override public void setNext(IMonoLink<E> next) { this.next = next; } // (3)
@Override public IMonoLink<E> getNext() { return this.next; } // (4)
@Override public String toString() {
return this.data.toString() + (this.next == null? “” : “, ” + this.next);
}
}
A generic interface can be implemented by a generic (or a non-generic) class:
class MonoNode<E> implements IMonoLink<E> {
// …
}
Note that the construct <E> is used in two different ways in the class header. The first occurrence of <E> declares E to be a type parameter, and the second occurrence of <E> parameterizes the generic interface with this type parameter. The declare-before-use rule also applies to type parameters. The version of the MonoNode class in Example 11.3 differs from the Node class in Example 11.2 at (1), (2), (3), and (4). These changes were necessary to make the MonoNode<E> class compliant with the IMonoLink<E> interface.
A generic interface can be parameterized in the same way as a generic class. In the code below, the reference strNode has the parameterized type IMonoLink<String>. It is assigned the reference value of a node of inferred type MonoNode<String>. The assignment is legal, since the parameterized type MonoNode<String> is a subtype of the parameterized type IMonoLink<String>:
IMonoLink<String> strNode2 = new MonoNode<>(“Bye”, null);
System.out.println(strNode2.getData()); // Prints: Bye
As with non-generic interfaces, generic interfaces cannot be instantiated either:
IMonoLink<String> strNode3 = new IMonoLink<>(“Bye”, null); // Compile-time error!
Example 11.4 shows a non-generic class implementing a generic interface. The generic interface IMonoLink<E> is parameterized by a concrete type, namely, Lymph. The type LymphNode is a subtype of the parameterized type IMonoLink<Lymph>, as it implements the methods of the generic interface IMonoLink<E> in accordance with the concrete type parameter Lymph.
The Java standard library contains many examples of generic interfaces. The two interfaces java.lang.Comparable<E> and java.util.Comparator<E> are discussed in detail in §14.4, p. 761, and §14.5, p. 769, respectively. The Java Collections Framework also includes many examples of generic interfaces, such as Collection<E>, List<E>, Set<E>, and Map<K,V> (Chapter 15, p. 781).
Example 11.4 A Non-Generic Class Implementing a Generic Interface
// File: LymphNode.java
class Lymph { /*… */ }
public class LymphNode implements IMonoLink<Lymph> {
private Lymph body;
private IMonoLink<Lymph> location;
@Override public void setData(Lymph obj) { body = obj; }
@Override public Lymph getData() { return body; }
@Override public void setNext(IMonoLink<Lymph> loc) { this.location = loc; }
@Override public IMonoLink<Lymph> getNext() { return this.location; }
}
Leave a Reply