Object-Oriented Programming in Java
Generics
Module VII: Generics. Generics allow you to create classes, methods, and interfaces that operate on data of specific types while ensuring type-safety at compile time. They are widely used in Java Collections, utility classes, and reusable APIs.
Basics of Generics
Generics enable writing type-independent code. Instead of using Object or casting manually, generics ensure compile-time checking.
- Eliminates unsafe type casting
- Enables strong type-checking
- Allows reusable, flexible classes and methods
ArrayList<String> list = new ArrayList<>();
list.add("hello");
// list.add(10); // compile-time errorDiagram: generic-type-parameter.png
Generic Class
A generic class defines one or more type parameters to be used in the class.
class Box<T> {
T value;
Box(T value) {
this.value = value;
}
T get() { return value; }
}
Box<Integer> b = new Box<>(100);
System.out.println(b.get());T,E,K,Vare common type parameter names- You can define multiple type parameters, e.g.
Box<T, U>
Generic Class with Two Type Parameters
class Pair<K, V> {
K key;
V value;
Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
Pair<String, Integer> p = new Pair<>("age", 20);Useful in maps, key-value data storage, and utility methods.
Generic Methods
A method can declare its own type parameter independent of the class.
class Utils {
static <T> void print(T value) {
System.out.println(value);
}
}
Utils.print("hello");
Utils.print(123);Diagram: generic-method-flow.png
Bounded Type Parameters
Bounds restrict the types that can be passed to generics.
class Numbers<T extends Number> { // only Number subclasses allowed
T num;
Numbers(T num) { this.num = num; }
}
Numbers<Integer> n1 = new Numbers<>(10);
Numbers<String> n2 = new Numbers<>("hi"); // errorBounded generics are widely used in sorting, comparisons, and collections.
Wildcards
Wildcards allow flexibility when working with unknown or partially known types.
- ? – unknown type
- ? extends T – upper bounded
- ? super T – lower bounded
void show(List<?> list) { } // accepts any type
void showNum(List<? extends Number> l) // only Number or its subclassesDiagram: wildcards-hierarchy.png
Type Erasure
Java implements generics using type erasure. After compilation, all generic type information is removed and replaced with raw types.
- Generic type parameters exist only at compile time
- Ensures backward compatibility with older Java versions
- Restrictions: no primitive generics, no runtime type-checking of generic types
ArrayList<Integer> a1 = new ArrayList<>(); ArrayList<String> a2 = new ArrayList<>(); // at runtime: a1.getClass() == a2.getClass(); // true
Summary
Generics help ensure type-safety and reusable code. Understanding generic classes, methods, wildcards, and type erasure prepares you for Java Collections, frameworks, and industry-level application development.
Diagrams to insert: generic-class-diagram.png, wildcard-usage.png