5) Generics Lesson

What is Java Generics?

8 min to complete · By Ryan Desmond

Java Generics is a way in Java to avoid specifying a certain data type for classes and methods and instead choose a flexible data type, thus making your program flexible.

How Generics Work

Until now, you have been told that specifying the type is required whenever creating something in Java. While this remains true, a generic data type is a type that allows for the value to be any object type, excluding bounded types - more on this soon, without causing an error.

This is made possible since the class definitions of the generic types support abstraction, thus allowing them to accept all types, but the instantiation of the class (into an object) indicates the data type. Thanks to a set of diamond brackets <>, the instantiation of the object is also made aware of the data types of variables to expect. Crystal clear? If not, take a look at an example, and that should help clear things up.

Java Generics Example

You've actually already been using generics. The ArrayList is a generic class. Imagine if the creators of Java had to write an individual ArrayList class for each and every possible data type that a person might ever want to put into an ArrayList. The ArrayList class itself must have pre-defined variables of specific data types in order to handle them properly. For example, imagine the add() method had to know what type of data to accept as an argument and place into the ArrayList.

If you built a specific ArrayList just to hold Strings, then the .get() method would have a return type of "String". This, by definition, would only work with Strings. So if you wanted an ArrayList that handled Integers, you would have to write a new class and have the get() method return an Integer.

This simply will not do. Instead, you can declare a Generic ArrayList class where the data type is abstracted away by the author of the class, and the specific type is given by the user. For instance, ArrayList<String> myList = new ArrayList(); In this line, you are telling the ArrayList what its data type is. By using Generics, you only need to write a single class that can accept multiple types of data. 

Take a look below at the ArrayList class:

/* generic class ArrayList<E> - note the "<E>" - when 
    authored, this class was left generic - when created 
    by the user using the <> brackets, the "E" is
    replaced by whatever data type the user defined 
    - i.e., ArrayList<String> myList = new ArrayList() 
    - this would replace "E" everywhere with "String" */

public class ArrayList<E> implements List<E> .... {
  /* Constructor */
  public ArrayList() { ... }

  /* Public methods */
  public boolean add(E e) { ... }

  public void add(int index, E element) { ... }

  public boolean addAll(
      int index, Collection<? extends E> c) { ... }

  /* notice this get() method - the return type is 
      again "E" which is replaced by the data 
      type in the <> operator */
  public E get(int index) { ... }

  public E remove(int index)
  // ...
}

Right away, you can see the diamond brackets in the definition of the ArrayList class. You might have noticed as well that the letter E is written in multiple places. This is something referred to as type erasure, and one of two new concepts that are important to take note of - continue reading for more information.

Important Concepts

Type Erasure

An important concept to remember is that the Generic type parameters are replaced at compile time by Java. As mentioned in the example above, E will be replaced by "String" everywhere E is present. This process is called type erasure. (Every E is erased and replaced with the type that the user declares in the diamond brackets <>.)

Type Inference

As of Java 7, you do not need to specify the Generic data type in <> brackets twice. For example:

ArrayList<String> myList = new ArrayList<String>();

can be replaced with:

ArrayList<String> myList = new ArrayList<>();

Soon, you'll dive into all things Generics so you can write your own highly customizable and flexible classes that will work with any data type in Java.

Summary: What is Java Generics

  • Generics is a functionality in Java that allows for flexible type declaration
  • Class definitions of generics type support abstraction
  • Class definitions of generics don't require type information
  • You indicate the data type of a generic class when you instantiate an object of a generic class
  • An ArrayList is an example of generics in Java - for instance ArrayList<String> words = new ArrayList();
  • Type erasure is when generic type parameters are replaced at compile time. For instance, all the method parameter types and return types in the ArrayList class
  • Type inference is when the instantiating constructor can infer the type in its declaration. For instance, ArrayList<String> words = new ArrayList(); instead of ``ArrayList words = new ArrayList ();`