Generic Classes in Java
A courier box can carry a book, a phone or a sweet box; the box doesn't care what's inside, but the label must say what it holds. A generic class is that box in code. You write the class once, with a placeholder type like T, and each time someone uses it they fill in the real type: a Box<String>, a Box<Integer>. The compiler then checks every use against that label.
Writing a Generic Class
public class Boxes {
static class Box<T> {
private T value;
Box(T value) { this.value = value; }
T get() { return value; }
void put(T value) { this.value = value; }
boolean isEmpty() { return value == null; }
}
public static void main(String[] args) {
Box<String> name = new Box<>("Navika");
Box<Integer> marks = new Box<>(91);
String upper = name.get().toUpperCase();
int bonus = marks.get() + 5;
System.out.println(upper + " " + bonus);
marks.put(95);
System.out.println(marks.get() + " " + name.isEmpty());
}
}NAVIKA 96
95 falseHow it works
class Box<T>declares a type parameterTright after the class name.- Inside the class,
Tis used like any type: the fieldT value, the parameter ofput, the return type ofget. Box<String>fillsTwithString. For that box,get()returns aStringandputaccepts only aString.- The same class serves
Box<Integer>, with no new code.
Several Type Parameters
A class can have as many type parameters as it needs, separated by commas:
public class Pairs {
record Pair<K, V>(K key, V value) {
@Override
public String toString() { return key + " = " + value; }
}
public static void main(String[] args) {
Pair<String, Integer> marks = new Pair<>("Srihitha", 88);
Pair<String, Boolean> passed = new Pair<>("Srihitha", true);
System.out.println(marks);
System.out.println(passed.value() ? "passed" : "failed");
}
}Srihitha = 88
passedPair<K, V> is a generic record: records can take type parameters just like classes. K and V are filled independently, so Pair<String, Integer> and Pair<String, Boolean> are both possible.
Common Mistakes
Calling type-specific methods on T. Inside Box<T>, you can only call Object methods on value, because T could be anything.
Using T in a static field or method of the class. Each instance can have a different T, so static members can't use it (see "Restrictions of Generics in Java").
Creating new T(). The type isn't known at runtime; pass a Supplier<T> instead.
Practice
- Easy: Write
class Wallet<T>holding a list of items of typeT, withadd(T)andcount(). Use it asWallet<String>for coupon codes. - Harder: Write a generic
Result<T>record with aT valueand aString error, plus static factoriesok(T value)andfail(String error). Return it from a method that parses a number.
Key Takeaways
Was this tutorial helpful?