Generics is a powerful feature in Java that allows you to write reusable and type-safe code by introducing type parameters. Generics enable you to create classes, methods, and interfaces that can work with different data types while providing compile-time type checking. In this Core Java tutorial, we'll explore generics in detail, providing explanations and examples.
What Are Generics?
Generics in Java allow you to define classes, interfaces, and methods with type parameters (also known as type variables). These type parameters act as placeholders for actual types that are determined at compile time. This enables you to write code that works with various data types while maintaining type safety.
Benefits of Generics:
Type Safety: Generics provide compile-time type checking, reducing the chances of runtime type errors.
Code Reusability: Generics allow you to write reusable code that can work with different data types.
Improved Readability: Code using generics is often more self-explanatory and less error-prone.
Generic Classes:
To create a generic class, you specify one or more type parameters when defining the class. These type parameters can be used as placeholders for the actual types that the class will work with.
Example of a Generic Class:
public class Box {
private T value;
public Box() {
// Constructor
}
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
In this example, the 'Box' class is generic, with a type parameter 'T'. It can store and retrieve values of any type.
Using a Generic Class:
public class GenericClassExample {
public static void main(String[] args) {
// Creating a Box for Integer
Box intBox = new Box<>(42);
int value = intBox.getValue(); // No need for casting
// Creating a Box for String
Box stringBox = new Box<>("Hello, Generics!");
String text = stringBox.getValue(); // No need for casting
}
}
In this example, we create instances of the 'Box' class with different types ( 'Integer' and 'String') without casting, thanks to generics.
Generic Methods:
You can also create generic methods that have their own type parameters, separate from the class's type parameters. This allows you to write methods that work with specific types while still benefiting from type safety.
Example of a Generic Method:
public class GenericMethodExample {
public static void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
In this example, the 'printArray' method is generic, and it can print arrays of any type.
Using a Generic Method:
public class GenericMethodUsage {
public static void main(String[] args) {
Integer[] intArray = { 1, 2, 3, 4, 5 };
String[] strArray = { "apple", "banana", "cherry" };
GenericMethodExample.printArray(intArray); // Prints integers
GenericMethodExample.printArray(strArray); // Prints strings
}
}
In this example, we call the 'printArray' method with arrays of different types, and it works correctly for both.
Wildcards in Generics:
Java also provides wildcards ( '?') to work with generic types in a more flexible way. Wildcards allow you to write methods or classes that operate on an unknown type or a specific type and its subtypes.
Example of Wildcards:
public class WildcardExample {
public static double sum(List numbers) {
double total = 0.0;
for (Number number : numbers) {
total += number.doubleValue();
}
return total;
}
}
In this example, the 'sum' method takes a list of numbers or its subtypes ('Integer', 'Double', etc.) using the '? extends Number' wildcard.
Using Wildcards:
public class WildcardUsage {
public static void main(String[] args) {
List integers = Arrays.asList(1, 2, 3);
List doubles = Arrays.asList(1.1, 2.2, 3.3);
double intSum = WildcardExample.sum(integers);
double doubleSum = WildcardExample.sum(doubles);
System.out.println("Integer Sum: " + intSum);
System.out.println("Double Sum: " + doubleSum);
}
}
In this example, we use the 'sum' method with lists of 'Integer' and 'Double', and it computes the sum correctly.
Conclusion:
Generics in Java provide a powerful way to write reusable and type-safe code. Whether you need to create generic classes, methods, or work with wildcards, generics enhance code readability, maintainability, and type safety. Understanding and using generics effectively is an essential skill for Java developers.