Why are generics used and its advantages in Java?
Types with parameters include generics. It is intended to allow types (such as integer, string, and user-defined types) to be passed as parameters to methods, classes, and interfaces. Classes with interactions with different data types can be created using generics. A generic object is one that operates on a type that has parameters, including a class, method, or function.
Why we use the generics?
The Object references can be utilized to connect to any object, while all other types are subclass of the Object. In numerous characteristics, it is lacking type safety. Generic medications include such kind of safety measure. This type of safety element will be covered in later examples.
Generics in Java are similar to templates in C++. For instance, classes such as the HashSet, ArrayList, HashMap, etc. effectively employ generics. There are numerous important differences between the two strategies for handling generic types.
Java Generics Types
Generic methods: An operation is carried out via a generic Java method, which subsequently returns a value. This generic methodology comprises elementwise some of which are specified based on the actual type, just like a regular function would. This makes it possible for the general technique to be used more widely. Programmers can create code more rapidly since they are not forced to perform time-consuming, specific type casts since the compilers handles type safety.
Generic Classes: A generic class's implementation is typically the same as a non-generic class. The only difference seems to be the inclusion of such a type variable section. There may be various parameter kinds, and each one would be separated by a comma. If the classes accept one or more parameters, they are refereed to that as parameterized classes or parametric types.
Generic Class
We utilise <> to define argument types when creating generic classes, just like in C++. The syntax used to generate instances of the generic class is as follows.
// A generic class instance should be created.
BaseTypes <Types> srj = new BaseType <Type>()
Note: Please take note that primitive types like "int," "char," and "double" cannot be used with parameter types.
File name: Kamal.java
// Java programme to demonstrate how user-defined
//generic classes function
// To specify the parameter type, we use < >
class Kamal<T> {
// The declaration of such an object of the type T
T srj;
Kamal(T srj) { this.srj = srj; } // using the constructor
public T getObject() { return this.srj; }
}
// Loading of the Driver class for tesing above
class Main {
public static void main(String[] args)
{
// the Integer type instance
Kamal<Integer> sSrj = new Kamal<Integer>(20);
System.out.println(sSrj.getObject());
// the Integer type instance
Kamal<String> hSrj
= new Kamal<String>("Poonakalu");
System.out.println(hObj.getObject());
}
}
Output:
20
Poonakalu
Generic classes allow us to pass numerous Type parameters as well.
File name: Sahi.java
// Program in Java to display many
// type arguments in Java Generics
// To specify the Parameter type, we use < >
class Sahi<T, U>
{
T srj1; // A T-type object
U srj2; // A U-type object
// It is the constructor
Sahi(T srj1, U srj2)
{
this.srj1 = srj1;
this.srj2 = srj2;
}
// Printing T and U-based objects
public void print()
{
System.out.println(srj1);
System.out.println(srj2);
}
}
// Loading the Driver class to test the above
class Main
{
public static void main (String[] args)
{
Sahi <String, Integer> srj =
new Kamal<String, Integer>("Boss", 25);
srj.print();
}
}
Output:
Boss
25
Generic Functions:
We can also create generic functions that, depending on the kind of arguments supplied to the generic method, can be called with various different types of arguments. Each method is dealt with by the compiler.
File name: Sahi1.java
// Java program that illustrates the usage of
// user-defined functions and generic functions
class Sahi1{
// An example of Generic method
static <T> void genericDisplay(T item)
{
System.out.println(item.getClass().getName()
+ " = " + item);
}
// Loading the Driver method
public static void main(String[] args)
{
// calling a general-purpose method with an integer parameter
genericDisplay(21);
// using a String argument when calling a generic method
genericDisplay("Simha");
// calling a general-purpose procedure with two arguments
genericDisplay(2.0);
}
}
Output:
java.lang.Integer = 21
java.lang.String = Simha
java.lang.Double = 2.0
Only reference types are compatible with generics:
The only reference types that work with generics are those that are supplied as type arguments towards the type parameter when a generic type instance is declared. We are unable to utilise primitive data types such int and char.
A compile-time error is produced by the line
Test <int> srj = new Test <int> (20);
This error can be fixed by enclosing a primitive type in type wrappers.
Arrays, however, are reference types, therefore they can be provided as the type argument along with arrays of primitive types.
ArrayList1<int[]> a = new ArrayList1< >();
Generic Types Vary According to Type Arguments:
Have a look at the Java code below.
File name: Sahi2.java
// An example Java programme
// for user-defined Generic classes
// To indicate a parameter type, we use the < >
class Sahi2<T> {
// A T-type object is declared.
T srj;
Sahi2(T srj) { this.srj = srj; } // Using the constructor
public T getTheObject() { return this.srj; }
}
// Loading the Driver class to test above
class Main {
public static void main(String[] args)
{
// instance of the integer type
Sahi2<Integer> sSrj = new Sahi2<Integer>(25);
System.out.println(sSrj.getObject());
// example of the String type
Sahi2<String> hSrj
= new Sahi2<String>("TATA");
System.out.println(hSrj.getObject());
sSrj = hSrj; // This leads to an error.
}
}
Output:
error:
incompatible types:
Sahi2 cannot be converted to Sahi2
sSrj and hSrj are reference to different types even though they are both objects of type Test even though their type parameters vary. By doing this, generics enhance type safety and guard against mistakes.
Java Generics Type Parameters
To fully understand generics, one must get familiar with the naming conventions for type parameters. These are the typical type parameters:
T = Type, E = Element, K = Key, N = Number, V = Value.
Benefits of Generics: When compared to non-generic code, programmes that employ generics have various advantages.
- Code Reusability: We are able to build a method, class, or interface just for once and apply it to any type we desire.
- Type Safety: Generics cause faults to show up at build time rather than at run time (It is always preferable to identify flaws within your code at compilation time rather than having the code fail at run time). Let's say you wish to create an array list to store student names. If by accident the coder includes an integer object as opposed to a string, then compiler will permit it. The difficulty arises at runtime whenever we extract this data from the ArrayList.
File name: Sahi3.java
// Java program to show how the use of generics
// might result in run-time exceptions
import java.util.*;
class Sahi3
{
public static void main(String[] args)
{
// making an ArrayList1 without specifying a type
ArrayList1 b1 = new ArrayList1();
b1.add("Kamal");
bl.add("Konda");
bl.add(20); // Compiler permits this.
String sr1 = (String)bl.get(0);
String sr2 = (String)bl.get(1);
// generates a runtime exception
String sr3 = (String)bl.get(2);
}
}
Output:
Exception in thread "main" java.lang.ClassCastException:
java.lang.Integer cannot be cast to java.lang.String
at Test.main(Sahi4.java:19)
How Can Generics Address This Issue?
We can declare that an ArrayList1 can only include String objects when defining the list.
File name: Sahi4.java
// Run-time exceptions become
// compile-time exceptions when Java Generics are used.
import java.util.*;
class Sahi4
{
public static void main(String[] args)
{
// making an ArrayList1 with the supplied String
ArrayList1 <String> bl = new ArrayList1<String> ();
bl.add("Kamal");
bl.add("Konda");
// Currently, the compiler wont this.
bl.add(20);
String sr1 = (String)bl.get(0);
String sr2 = (String)bl.get(1);
String sr3 = (String)bl.get(2);
}
}
Output:
15: error: no suitable method found for add(int)
bl.add(20);
^
- Separate Type Casting also isn't Required: If we choose to not utilise generics, therefore, in the example above, we must typecast the data each time we retrieve it from the ArrayList. At every retrieval procedure, typecasting is a major pain. If we are already aware that each list only contains string data, we do not need to typecast it each time.
- Generics Encourage Code Reusability: Java's generics feature makes it possible to design code that will function with a variety of data types. for instance
public <T> void genericsMethod (T data) {...}
This is a generics approach that we developed. Using the integer data, string data, and other types of data, this method can be applied to conduct operations.
- Using Generics to Implement Algorithms: Generics allow us to implement algorithms that are both type-safe and flexible enough to work with many sorts of objects.