English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In this tutorial, we will learn about Java generics through examples, how to create generic classes and methods, and their advantages.
In Java,GenericIt helps to create classes, interfaces, and methods that can be used with different types of objects (data). Therefore, it allows us to reuse our code.
Note:Note:GenericGenerics are not applicable to primitive types (int, float, char, etc.).
To understand how to useGenericwe can use classes from the Java collection framework.
The ArrayList class is an example of a generic class. We can use ArrayList to store any type of data. For example
import java.util.ArrayList; class Main { public static void main(String[] args) { //Create an array list to store Integer data ArrayList<Integer> list1 = new ArrayList<>(); list1.add(4); list1.add(5); System.out.println("ArrayList of Integer: ") + list1); //Create an array list to store String data ArrayList<String> list2 = new ArrayList<>(); list2.add("Four"); list2.add("Five"); System.out.println("ArrayList of String: ") + list2); //Create an array list to store Double data ArrayList<Double> list3 = new ArrayList<>(); list3.add(4.5); list3.add(6.5); System.out.println("ArrayList of Double: ", + list3); } }
Output result
ArrayList of Integer: [4, 5] ArrayList of String: [Four, Five] ArrayList of Double: [4.5, 6.5]
In the above example, we used the same ArrayList class to store elements of types Integer, String, and Double. SinceJava generics, which is possible.
Please note this line here,
ArrayList<Integer> list1 = new ArrayList<>();
We used Integer inside the angle brackets <> in generics. Angle brackets <> are calledType parameters.
The parameter type is used to specify the type of object (data) that the generic class or method is applicable to.
Now that we know how generics work in Java, let's see how to create our own generic class.
class Main { public static void main(String[] args) { //Initialize the generic class with integer data GenericsClass<Integer> intObj = new GenericsClass<>(5); System.out.println("The generic class returns:", + intObj.getData()); //Initialize the generic class with string data GenericsClass<String> stringObj = new GenericsClass<>("Java Programming"); System.out.println("The generic class returns:", + stringObj.getData()); } } class GenericsClass<T> { //Type variable T private T data; public GenericsClass(T data) { this.data = data; } //Method to return a variable of type T public T getData() { return this.data; } }
Output result
The generic class returns: 5 The generic class returns: Java Programming
In the above example, we created a generic class named GenericsClass. This class can be used to handle any type of data.
class GenericsClass<T> {...}
Here, T representsType parametersInside the Main class, we created GenericsClass objects named intObj and stringObj.
When creating intObj, the type parameter T is replaced with Integer. This means that intObj uses GenericsClass to handle integer data.
When creating stringObj, the type parameter T is replaced with String. This means that stringObj uses GenericsClass to handle string data.
Similar to generic classes, we can also create our own generic methods in Java.
class Main { public static void main(String[] args) { //Using Integer data to initialize the class DemoClass demo = new DemoClass(); demo.<String>genericMethod("Java Programming"); } } class DemoClass { //Generic methods public <T> void genericsMethod(T data) { System.out.println("This is a generic method."); System.out.println("The data passed to the method is "); + data); } }
Output result
This is a generic method. The data passed to the method is: Java Programming
In the above example, we created a generic method named genericsMethod within a regular class (DemoClass).
public <T> void genericMethod(T data) {...}
Here, the type parameter <T> is inserted after the modifier (public) and before the return type (void).
We can call a generic method by placing the actual type <String> in front of the method name in the parentheses.
demo.<String>genericMethod("Java Programming");
Note: In most cases, we can omit the type parameter when calling a generic method. This is because the compiler can use the value passed to the method to match the type parameter. For example,
demo.genericsMethod("Java Programming");
Generally speaking,Type parameterIt can accept any data type (except primitive types). However, if we want to use generics only for certain specific types (such as accepting numeric data types), we can use bounded types.
We use the extends keyword. For example,
<T extends A>
This means that T can only accept data types that are subclasses of A.
class GenericsClass<T extends Number> { public void display() {}} System.out.println("This is a bounded type generics class."); } } class Main { public static void main(String[] args) { //Create a GenericsClass object GenericsClass<String> obj = new GenericsClass<>(); } }
In the above example, we created abounded typeof the generic class. Here, note the expression
<T extends Number>
This means that T can only use subtypes of Number data types (Integer, Double, etc.).
However, we have already created an object of the generic class using String. This is why when we run the program, we get the following error.
GenericsClass<String> obj = new GenericsClass<>(); ^ reason: inference variable T has incompatible bounds equality constraints: String lower bounds: Number where T is a type-variable: T extends Number declared in class GenericsClass
GenericThis allows us to write code that is applicable to different types of data. For example,
public <T> void genericsMethod(T data) {...}
Here, we create a generic method. This method can be used to perform operations on integer data, string data, and so on.
GenericType parameterProvide information about the data type used in generic code.
Therefore, any errors can be identified at compile time, which is easier to fix than runtime errors. For example,
//Without using generics NormalClass list = new NormalClass(); //Calling the method of NormalClass list.display("String");
In the above code, we have a regular class. We call the method named display() of this class by passing string data.
Here, the compiler does not know if the value passed in the parameter is correct. But let's see what happens if we use a generic class instead.
//Use generics GenericsClass<Integer> list = new GenericsClass<>(); //Call the method of GenericsClass list2.display("String"); In the above code, we have a generic class. Here, the type parameter indicates that this class is processing Integer data. Therefore, when string data is passed as a parameter, the compiler will generate an error.
The collection framework uses the generic concept in Java. For example,
// Create a string type ArrayList ArrayList<String> list1 = new ArrayList<>(); // Create an integer type ArrayList ArrayList<Integer> list2 = new ArrayList<>();
In the above example, we used the same ArrayList class to handle different types of data.
Like ArrayList, other collections (LinkedList, Queue, Maps, etc.) are also Java generics.