Generics: Type-Safe Templates
Generics allow you to write a single class, interface, or method that can work with different types of data while providing compile-time type safety.
Before Generics, you had to use the Object class and cast everything, which often led to ClassCastException crashes at runtime. Generics catch these errors while you are still writing the code.
1. The Syntax: Angle Brackets <T>
The <T> is a placeholder for a Type. When you create an instance of the class, you replace T with a real type like Integer or String.
// A generic class that can hold any type of object
public class Box<T> {
private T content;
public void set(T content) { this.content = content; }
public T get() { return content; }
}
2. Using Generics
When you use the class, you specify the type. Java handles the rest!
// Box for Strings
Box<String> stringBox = new Box<>();
stringBox.set("Hello c0der");
String s = stringBox.get(); // No casting needed!
// Box for Integers
Box<Integer> intBox = new Box<>();
intBox.set(101);
3. Generic Methods
You can also make a single method generic, even if the class it belongs to is not.
public static <E> void printArray(E[] elements) {
for (E element : elements) {
System.out.println(element);
}
}
4. Why Use Generics?
- Type Safety: You get an error at compile-time if you try to put a
Stringinto aBox<Integer>. - Elimination of Casts: You don't have to manually convert types (e.g.,
(String) myObject). - Code Reuse: You write the logic once and apply it to many data types (like how
ArrayList<T>works).
💻 Full Practical Example: The Key-Value Pair
Copy this to see how you can use multiple generic parameters (usually K for Key and V for Value):
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void display() {
System.out.println("Key: " + key + " | Value: " + value);
}
}
public class Main {
public static void main(String[] args) {
// Mapping an ID (Integer) to a Name (String)
Pair<Integer, String> user = new Pair<>(101, "Ahmed");
user.display();
// Mapping a Config (String) to a Status (Boolean)
Pair<String, Boolean> config = new Pair<>("darkMode", true);
config.display();
}
}
5. Naming Conventions
While you can use any letter, these are the standard ones used by Java developers:
T- TypeE- Element (used extensively by the Collections framework)K- KeyV- ValueN- Number
💡 Challenge: The Generic Swap
Write a generic method called swap(T[] array, int i, int j).
- The method should take an array of any type.
- It should swap the elements at the two given indices.
- Test it in
mainwith an array of Strings and an array of Integers.