Generics and wildcards
Generics (Java 5) let classes and methods work with any type while keeping compile-time type safety: no casts and no surprise ClassCastException.
- Generic class:
class Box<T> - Generic method:
static <T> T first(List<T> list) - Bounded type:
<T extends Number> - Diamond operator (Java 7):
new ArrayList<>()
Wildcards follow the PECS rule, Producer Extends, Consumer Super:
List<? extends Number>: you can read Numbers from it (it produces values).List<? super Integer>: you can add Integers to it (it consumes values).
Why generics
Generics let the compiler check types for you. Without them, a list holds Object and every read needs a cast that can fail at run time. With them, mistakes become compile errors.
List<String> names = new ArrayList<>();
names.add("Asha");
// names.add(42); // compile error
String first = names.get(0); // no cast neededGeneric classes
Declare type parameters in angle brackets. The diamond operator <> lets the compiler infer them when you create an object.
public class Box<T> {
private final T value;
public Box(T value) { this.value = value; }
public T get() { return value; }
}
Box<Integer> b = new Box<>(42);
record Pair<A, B>(A first, B second) {}Generic methods
A method can have its own type parameter, declared before the return type. The compiler usually infers it from the arguments.
static <T> T firstOrDefault(List<T> list, T fallback) {
return list.isEmpty() ? fallback : list.get(0);
}
String s = firstOrDefault(List.of("a"), "none");Bounded type parameters
<T extends Number> limits T to Number and its subtypes, so you can call Number methods on it. Several bounds are joined with &.
static <T extends Comparable<T>> T max(List<T> items) {
T best = items.get(0);
for (T item : items) if (item.compareTo(best) > 0) best = item;
return best;
}Wildcards and PECS
List<? extends Number>: you can read Numbers from it (a producer), but not add.List<? super Integer>: you can add Integers to it (a consumer).List<?>: any type, read asObject.
Remember PECS: Producer Extends, Consumer Super.
static double sum(List<? extends Number> nums) {
double total = 0;
for (Number n : nums) total += n.doubleValue();
return total;
}
static void fill(List<? super Integer> out) { out.add(1); out.add(2); }
sum(List.of(1, 2.5, 3L)); // works for Integer, Double, LongType erasure and its limits
Generic types exist only at compile time; the compiler erases them to their bounds. So at run time you can't do new T(), instanceof List<String> or create a new T[10] array, and List<String> and List<Integer> are the same class.
Raw types
Using a generic class without type arguments (List list = new ArrayList();) is a raw type, kept only for pre-Java 5 code. It turns off type checking and produces warnings; never use it in new code.
Example
class Box<T> {
private final T value;
Box(T value) { this.value = value; }
T get() { return value; }
}
static <T extends Comparable<T>> T max(List<T> items) {
T best = items.get(0);
for (T t : items) if (t.compareTo(best) > 0) best = t;
return best;
}
static double total(List<? extends Number> nums) { // producer: read from it
double sum = 0;
for (Number n : nums) sum += n.doubleValue();
return sum;
}
static void fill(List<? super Integer> sink) { // consumer: write to it
sink.add(1);
sink.add(2);
}
Box<String> b = new Box<>("hi");
System.out.println(max(List.of(3, 9, 4))); // 9Common mistake
Using raw types such as List list = new ArrayList(); You lose type checking and get unchecked warnings. Always give the type argument.
Under the hood
Generics use type erasure: List<String> and List<Integer> are the same class at runtime, so you can't write new T(), T.class or instanceof List<String>. Frameworks recover type information from class signatures instead, for example Jackson's TypeReference or Spring's ParameterizedTypeReference, which use an anonymous subclass so the type argument is recorded.
Check yourself
Which list can you safely add an Integer to?
How this connects
Know these first
Where this leads
You've reached the end of this thread. Try a learning path for what's next.
Part of Java from zero, Job-ready backend developer, Crack the Java interview.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.