Java Generics – Complete Guide with Examples
Learn Java Generics to create type-safe classes, methods, and collections, understand generic types, wildcards, and how to use them for reusable and robust code.
Generics in Java – Complete Detailed Tutorial
Generics allow classes, interfaces, and methods to operate on types specified as parameters, providing compile-time type safety and reducing runtime errors.
1. What are Generics?
- Introduced in Java 5
- Parameterizes types (like templates in C++)
- Ensures type safety at compile time
- Eliminates need for casting objects
Syntax:
class ClassName<T> {
T data; // T is a type parameter
void setData(T data) { this.data = data; }
T getData() { return data; }
}
Tis a type parameter- Can also use E (Element), K (Key), V (Value), N (Number)
2. Generic Class Example
class Box<T> {
private T content;
public void setContent(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
public class Main {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setContent("Hello Generics");
System.out.println("String Box: " + stringBox.getContent());
Box<Integer> intBox = new Box<>();
intBox.setContent(100);
System.out.println("Integer Box: " + intBox.getContent());
}
}
Output:
String Box: Hello Generics
Integer Box: 100
Key Points:
- Type specified at object creation
- Provides compile-time type checking
3. Generic Method
- Methods can also be generic
- Use
<T>before return type
class Utils {
public static <T> void printArray(T[] array) {
for(T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
}
public class Main {
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3};
String[] strArray = {"A", "B", "C"};
Utils.printArray(intArray);
Utils.printArray(strArray);
}
}
Output:
1 2 3
A B C
4. Bounded Generics
- Restrict type parameter to subclass or interface
- Syntax:
T extends ClassName
class Calculator<T extends Number> {
public double square(T num) {
return num.doubleValue() * num.doubleValue();
}
}
public class Main {
public static void main(String[] args) {
Calculator<Integer> intCalc = new Calculator<>();
System.out.println("Square: " + intCalc.square(5));
Calculator<Double> doubleCalc = new Calculator<>();
System.out.println("Square: " + doubleCalc.square(3.5));
}
}
Output:
Square: 25.0
Square: 12.25
Key Points:
- Ensures only Number subclasses used
- Avoids type errors at compile time
5. Wildcards in Generics
- Unbounded wildcard:
<?>– any type - Upper-bounded wildcard:
<? extends Class>– subclass of Class - Lower-bounded wildcard:
<? super Class>– superclass of Class
import java.util.Arrays;
import java.util.List;
public class Main {
public static void printList(List<?> list) {
for(Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3);
List<String> strings = Arrays.asList("A", "B", "C");
printList(numbers);
printList(strings);
}
}
Output:
1 2 3
A B C
6. Key Points
- Generics provide type safety
- Reusability: same code works for multiple types
- Eliminates casting
- Works with classes, interfaces, methods, and collections
- Bounded types restrict type parameters
- Wildcards allow flexible method arguments
7. Summary
- Generics improve code readability, safety, and flexibility
- Widely used in Collections Framework
- Important for professional Java development