Java - Generics
Generics
Generics in Java is similar to templates in C++. In this article, we will go through Generics in Java.
Generics is the capability to parameterize types. With this capability, you can define a class or a method with generic types that can be substituted using concrete types by the compiler. The idea is to allow type (Integer, String, … etc, and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
An entity such as class, interface, or method that operates on a parameterized type is called generic entity.
Why Generics?
The key benefit of generics is to enable Errors to be detected at Compile-time rather than at Run-time.
In Java, Object is the superclass of all other classes and Object reference can refer to any type object. These features lack type safety. Generics adds that type safety feature.
A generic class or method permits you to specify allowable types of objects that the class or method may work with. If you attempt to use the class or method with an incompatible object, a Compile-time error occurs.
- Generics can help detect type errors at compile time, thus make programs more robust.
- Generics can make programs easy to read.
- Generics can avoid cumbersome castings.
What if we don’t use Generics?
Let’s look at this code. You will get a warning.
1 | public class ShowUncheckedWarning { |
The compiler will report warning and generate a class file if no other errors in the program.
Warning message:
1 | Note: ShowUncheckedWarning.java uses unchecked or unsafe operations. |
Here if we use ArrayList list = new ArrayList();
, This is roughly equalivalent to:ArrayList<Object> list = new ArrayList<Object>();
. Using raw Type is Unsafe and might cause Runtime error.
To fix the warning:
1 | public class ShowUncheckedWarning { |
Create Generics
We use <> to specify parameter types in generic class.
Let’s see a minimum Generic class example from GeeksForGeeks:
1 | // A Simple Java program to show working of user defined |
Note:
- In Parameter type we can not use primitives like ‘int’,‘char’ or ‘double’.
- A generic class can have multiple type parameters.
- Generic type information is present at compile time ONLY.
- A generic class is shared by all its instances regardless of its actual generic type.
- In above example, although
Test<Integer>
andTest<String>
are two types, but there is only one classTest
loaded into the JVM.
- In above example, although
Type Parameter Naming Conventions
By convention, type parameter names are single, uppercase letters.
The most commonly used type parameter names are:
-
E - Element (used extensively by the Java Collections Framework)
-
K - Key
-
V - Value
-
N - Number
-
T - Type
-
S,U,V etc. - 2nd, 3rd, 4th types
Multiple Type Parameters
- A generic class can have multiple type parameters.
For example, the generic OrderedPair class, which implements the generic Pair interface:
1 | interface Pair<K, V> { |
Because a Java compiler can infer the K and V types from the declaration OrderedPair<String, Integer>, these statements can be shortened using diamond notation
<>
.
Bounded Generic Type
There may be times when you’ll want to restrict the kinds of types that are allowed to be passed to a type parameter.
For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
To declare a bounded type parameter, list the type parameter’s name, followed by the extends
keyword, followed by its upper bound.
Example:
1 | public static void main(String[] args) { |
Restrictions on Generics
Create an Instance
Cannot Create an Instance of a Generic Type. (i.e., new E()).
You cannot create an instance using a generic class type parameter.
1 | E object = new E(); //Wrong |
Array Creation
Generic Array Creation is Not Allowed. (i.e., new E[100]).
You cannot create an array using a generic class type parameter or a generic class.
1 | //using generic type parameter |
Static Context
A Generic Type Parameter of a Class Is Not Allowed in a Static Context.
1 | public class Test < E > { // a Generic Class |
To correctly use Generic in Static Context:
1 | public class GenericMethodDemo { // Not a Generic Class |
Exception Classes
Exception Classes Cannot be Generic.
1 | public class MyException<T> extends Exception { } //Illegal |
If it were allowed, you would have a catch clause for MyException<T>
as follows:
1 | try { |
Example - Using Generics
Example : Using Generics to Create another Data Structure
MyStack.java
1 | import java.util.ArrayList; |
MyQueue.java
1 | import java.util.LinkedList; |
TestStackQueue.java
1 | public class TestStackQueue { |