Java Generic Interface

Generic represents the abstraction over types. Generics allows the developer to develop abstract Algorithms and Data structures which can be used with concrete types later. The Java Generics programming is introduced in J2SE 5 to deal with type-safe objects. Before generics, we can store any type of objects in collection i.e. non-generic. Now generics, forces the Java programmer to store specific type of objects.

To define a generic interface, we need to provide the type(s), and the type(s) should be parameterized. These parameters are also called Type parameter. Here is a small example from the definitions of the interfaces List and Iterator in package java.util:

public interface List <E> {
    void add(E x);
    Iterator<E> iterator();

public interface Iterator<E> {
    E next();
    boolean hasNext();

The stuff in angle brackets is the declaration of the formal type parameters of the interfaces List and Iterator. The interface is defined with parameterized type (E in this case) and during invocation of the implementation, the parameterized type will be replaced with actual type argument. Consider the following example with actual type:

For example consider List<Integer> stands for a version of List where E has been uniformly replaced by Integer:

public interface IntegerList {
    void add(Integer x);
    Iterator<Integer> iterator();

This above intuition is only for explanation, because the declaration of a generic is never actually expanded in this way. There aren't multiple copies of the code -- not in source, not in binary, not on disk and not in memory. A generic type declaration is compiled only once and that is for all, and turned into a single class file, just like an ordinary class or interface declaration.

Type parameters in generics are same as ordinary parameters used in methods or constructors. A method has formal value parameters that describe the kinds of values it can operates on. When a method is invoked, the actual arguments are substituted for the formal parameters, and the method body is evaluated.

Same as the generic declaration has formal type parameters, when a generic declaration is invoked, the actual type arguments are substituted for the formal type parameters. Consider the following example to check that generic class/interface has only one copy after the compilation :

public class GenericTest {

  public static void main(String[] args){
    List <String> aList = new ArrayList<String>();
    List<Integer> bList = new ArrayList<Integer>();
    System.out.println(aList.getClass() == bList.getClass());

What does the following code fragment print? It prints true, because all instances of a generic class have the same run-time class, regardless of their actual type parameters which is String for aList and Integer for bList.

Indeed, A generic class has the same behavior for all of its possible type parameters; the same class can be viewed as having many different types. As consequence, the static variables and methods of a class are also shared among all the instances. That is why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static variable.

Comparable interface is a great example of Generics interface and it’s written as:

package java.lang;
import java.util.*;

public interface Comparable<T> {
    public int compareTo(T o);

In similar way, we can create generic interfaces in java. We can also have multiple type parameters as in Map interface. Again we can provide parameterized value to a parameterized type also, for example new HashMap<String, List<String>>(); is valid.

core java 12


Explore Tutu'rself