# Generics

Generics were introduced in the JDK 5.0 as a language enhancement. Generics are heavily used Java Collection Framework interface. Generics can be used to define methods, classes and interfaces that can operate with different data types.

## Why Use Generics

1. Generics provide compile-time safety
2. Removes unnecessary type conversions

## Generic Interfaces

Generics are defined with the type in angle brackets, <> after the interface name.

Here is the definition of the java.util.Collection interface

public interface Collection<E> extends Iterable<E>


<E> defines the generic element that can passed to the Collection. The collection can be used as follows to define a collection that can only contain String types :

Collection<String> collection;


or a collection that holds Integer types as follows :

Collection<Integer> collection;


We can replace <E> in Collection<E> with any type. We gain compile type safety checks from the compiler and also remove type conversion since we know the collection will always contain a specific type.

## Generic Classes

Generic classes are defined the same way as generic interfaces. The type is specified in angle brackets, <>.

Any ArrayList is an ordered collection of objects by their index. Here is the definition of the ArrayList generic class :

public class ArrayList<E> extends AbstractList<E> implements List<E>


Notice how the the class is defined with the <E>, ArrayList<E> and also inherits from a generic class and a generic interface. The <E> defines the ArrayList to be generic. It represents any element type. We can replace <E> with any data type. Here is how we can declare a variable of the ArrayList to hold Integer types :

ArrayList<Integer> list;


and to hold String types :

ArrayList<String> list;


## Instantiating Generic Classes

When instantiating a generic class we have to include the type in angle brackets, <>.

Here is an example of instantiating the generic ArrayList from above with types of String :

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


Since we have already defined the type to be a generic String, we can replace the new ArrayList<String>() with new ArrayList<>(), since its redundant as follows :

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


We could also define an ArrayList that can hold Integer types :

ArrayList<Integer> list = new ArrayList<>();


## Using Generic Methods

Methods can also be declared to be generic by using the same E specified in the generic class.

Here is the definition of the generic method add in the ArrayList class :

public boolean add(E e){}


To use the generic method add, we will have to pass in the correct type of E.

ArrayList<Integer> list = new ArrayList<>();


Notice the above generates a compile-time error when we try to pass in the wrong type. Without using generics the following will work :

ArrayList list = new ArrayList<>();
list.add(15.9); // works without an error


The above works because we did not limit the types the ArrayList can hold. The ArrayList hold types of Object. This code can cause run-time errors in future since we did not guarantee the types in the ArrayList.