Intermediate · Exceptions and generics · topic 29 of 60 · 30 min
Generics
Explanation
Why generics?
Before Java 5, a List held Objects. You could put a String and an Integer in the same list, and every read needed a cast that could fail at run time with ClassCastException. Generics move that check to compile time: List<String> accepts only Strings, and get returns a String with no cast.
List names = new ArrayList(); // raw type (old style): avoid
names.add("Asha");
names.add(42); // allowed!
String s = (String) names.get(1); // ClassCastException at run time
List<String> safe = new ArrayList<>(); // diamond <> infers <String>
safe.add("Asha");
// safe.add(42); // compile error
String first = safe.get(0); // no cast neededGeneric classes
public class Pair<K, V> {
private final K key;
private final V value;
public Pair(K key, V value) { this.key = key; this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> stock = new Pair<>("rice", 40);
int qty = stock.getValue(); // auto-unboxed IntegerGeneric methods
public static <T> T firstOrDefault(List<T> list, T fallback) {
return list.isEmpty() ? fallback : list.get(0);
}
String city = firstOrDefault(List.of("Pune", "Goa"), "Unknown"); // T inferred as StringBounded type parameters
public static <T extends Number> double sum(List<T> values) {
double total = 0;
for (T v : values) total += v.doubleValue(); // allowed: T is some Number
return total;
}
sum(List.of(10, 20, 30)); // 60.0 (Integers)
sum(List.of(2.5, 3.5)); // 6.0 (Doubles)
// sum(List.of("a")); // compile error: String is not a Number
public static <T extends Comparable<T>> T max(List<T> list) { … } // T must be comparableWildcards
A List<Integer> is NOT a List<Number>, even though Integer is a Number (otherwise you could add a Double to a list of Integers through the Number view). Wildcards express flexible parameters. The short rule is PECS: Producer Extends, Consumer Super.
static double total(List<? extends Number> prices) { … } // reads (produces) Numbers: Integer, Double lists OK
static void addDefaults(List<? super Integer> out) { // writes (consumes) Integers
out.add(0);
out.add(100);
}
List<Number> nums = new ArrayList<>();
addDefaults(nums); // OK: Number is a supertype of IntegerType erasure and its limits
The compiler checks generic types and then erases them: at run time, a List<String> and a List<Integer> are both just List. This keeps compatibility with old code but brings limits.
- No primitives as type arguments: List<int> does not compile; use List<Integer>.
- No new T() and no new T[10] inside a generic class (T is unknown at run time).
- No instanceof List<String>; only instanceof List<?> is allowed.
- Static fields cannot use the class's type parameter.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Generics · 1/6
In this lesson you will write type-safe reusable code with generics.
Prefer a video by a teacher? Find free videos on “java generics tutorial bounded types wildcards pecs type erasure” on YouTube ↗
In real life: A typed API response wrapper
A Spring Boot backend returns every response in the same envelope: success flag, data and error message. One generic record ApiResponse<T> works for a single order, a list of trains or a user profile, and the compiler checks the data type everywhere.
public record ApiResponse<T>(boolean success, T data, String error) {
public static <T> ApiResponse<T> ok(T data) { return new ApiResponse<>(true, data, null); }
public static <T> ApiResponse<T> fail(String error) { return new ApiResponse<>(false, null, error); }
}
ApiResponse<List<String>> trains = ApiResponse.ok(List.of("12951", "12627"));
ApiResponse<Integer> missing = ApiResponse.fail("Train not found");Practice (0/3 done)
Which line does NOT compile?
Given static double total(List<? extends Number> l), which call compiles?
Write a generic class Box<T> with a private T value, a constructor, get(), and a generic static method <T extends Comparable<T>> T maxOf(List<T> items) that returns the largest item (or throws IllegalArgumentException for an empty list). Test maxOf with a list of Integers and a list of Strings.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Avoiding NullPointerExceptionExceptions and generics · same module
- Checked vs unchecked exceptions and throwing your ownExceptions and generics · same module
- Generics: reusable, type-safe codeC# and .NET · Collections, generics and LINQ
- GenericsJavaScript Programming (language in depth) · TypeScript basics
- Generics: type parameters and constraintsGo Programming (backend and cloud) · Packages, testing and generics
- Generics and utility typesFrontend Web Development · TypeScript basics
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What do generics mainly give you?
Answer: Type safety at compile time without casts
Errors move from run time to compile time.
Is List<Integer> a subtype of List<Number>?
Answer: No
Generic types are invariant; use List<? extends Number>.
What is type erasure?
Answer: The compiler removing generic type information after checking it
At run time, List<String> is just List.
What does PECS stand for?
Answer: Producer Extends, Consumer Super
Read from ? extends, write to ? super.
Which is a generic type in .NET?Related
Answer: Dictionary<TKey,TValue>
Dictionary has two type parameters.
Which built-in type is generic?Related
In which Go version did generics arrive?Related
Answer: 1.18
Go 1.18 (March 2022) added type parameters.
In function findById<T extends { id: string }>(items: T[], id: string), what does T extends { id: string } mean?Related
Answer: T can be any type that has at least an id of type string
extends is a constraint: T may have more properties, but it must have id: string.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Exceptions and generics” before its exam: Avoiding NullPointerException.
- Module 6 exam: Exceptions and generics · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, The collections framework. 60 topics left in the course before the final exam.