Skip to main content

9. Generics in Java

πŸ“ Generics is a feature in Java that allows you to define classes, interfaces, and methods with a placeholder for types, enabling stronger type checks at compile-time and eliminating the need for type casting.

1. What are Generics?​

  • Generics enable you to create classes, interfaces, and methods that operate on specified types, known as type parameters.
  • They provide compile-time type safety and help avoid runtime ClassCastException.

2. Benefits of Using Generics​

  • Type Safety: Ensures that the data type being used is consistent throughout the code.
  • Elimination of Type Casting: Reduces the need for explicit casting.
  • Code Reusability: Allows the creation of generic algorithms that work on different data types.

3. Defining Generic Classes​

You can define a generic class by specifying a type parameter in angle brackets.

Example:​

class Box<T> {
private T item;

public void setItem(T item) {
this.item = item;
}

public T getItem() {
return item;
}
}

// Usage
public class GenericClassExample {
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello Generics");
System.out.println(stringBox.getItem());

Box<Integer> integerBox = new Box<>();
integerBox.setItem(123);
System.out.println(integerBox.getItem());
}
}

4. Defining Generic Methods​

You can also create methods that use generics, specifying the type parameter before the return type.

Example:​

public class GenericMethodExample {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.println(element);
}
}

public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4, 5};
String[] strArray = {"One", "Two", "Three"};

printArray(intArray); // Prints integer array
printArray(strArray); // Prints string array
}
}

5. Bounded Type Parameters​

You can restrict the types that can be passed to a type parameter using bounded type parameters.

Example:​

class ComparableBox<T extends Comparable<T>> {
private T item;

public void setItem(T item) {
this.item = item;
}

public T getItem() {
return item;
}

public T max(T other) {
return item.compareTo(other) > 0 ? item : other;
}
}

// Usage
public class BoundedTypeExample {
public static void main(String[] args) {
ComparableBox<Integer> intBox = new ComparableBox<>();
intBox.setItem(10);
System.out.println(intBox.max(20)); // Prints 20
}
}

6. Wildcards​

Wildcards are used when you want to specify a type that can be any type, using ?.

Types of Wildcards:​

  • Unbounded Wildcard: ? can represent any type.
  • Upper Bounded Wildcard: ? extends T allows any type that is a subclass of T.
  • Lower Bounded Wildcard: ? super T allows any type that is a superclass of T.

Example:​

import java.util.List;

public class WildcardExample {
public static void printList(List<?> list) {
for (Object element : list) {
System.out.println(element);
}
}

public static void main(String[] args) {
List<String> strings = List.of("A", "B", "C");
printList(strings); // Works with any type
}
}

7. Summary of Generics​

FeatureDescription
Type SafetyEnsures consistent data types at compile-time.
Elimination of Type CastingReduces the need for explicit casting.
Generic ClassesClasses defined with type parameters.
Generic MethodsMethods that operate on parameters of any specified type.
Bounded Type ParametersRestrict types using extends and super.
WildcardsRepresent unknown types (?, ? extends, ? super).

Generics are an essential feature in Java that improves code safety and reusability.