Cosmic Module
J
Qubits of DPK
March 15, 2026
Core Java
Layman Explanation
Imagine a box that can hold ANYTHING — but you want a box that only holds apples. If someone tries to put an orange in, you want an error immediately, not when you open the box later.
Generics let you create classes, methods, and interfaces that work with any type but are type-safe at compile time.
Real World Analogy
A printer that prints documents. Whether you give it a Word doc, PDF, or image — it prints anything. But it guarantees: what you put in is what comes out. You put in a PDF, you get a PDF back — not a random document.
What Are Generics?
Generics allow you to write classes, methods, and interfaces that are parameterized by type — meaning the type is a variable that gets resolved at compile time.
java
QUBITS OF DPK
Generic Class
java
QUBITS OF DPK
Multiple Type Parameters
java
QUBITS OF DPK
Generic Method
java
QUBITS OF DPK
Bounded Type Parameters
Restrict which types can be used as type arguments.
Upper Bounded — extends
java
QUBITS OF DPK
Multiple Bounds
java
QUBITS OF DPK
Wildcards
Wildcards use ? — represent an unknown type.
Unbounded Wildcard — <?>
java
QUBITS OF DPK
Upper Bounded Wildcard — <? extends Type>
java
QUBITS OF DPK
Lower Bounded Wildcard — <? super Type>
java
QUBITS OF DPK
PECS Rule — Producer Extends, Consumer Super
javascript
QUBITS OF DPK
Type Erasure — How Generics Work at Runtime
Generics are a compile-time feature only. At runtime, all type parameters are erased:
java
QUBITS OF DPK
The compiler inserts casts automatically based on the generic type information.
Generic Interface
java
QUBITS OF DPK
This is exactly how Spring Data JPA works — JpaRepository<Entity, ID> is a generic interface!
Production Use Cases
java
QUBITS OF DPK
️ All Traps
java
QUBITS OF DPK
30-Second Interview Answer
"Generics allow writing type-safe, reusable code by parameterizing types at compile time. Instead of List list (unsafe), you write List<String> list — the compiler enforces type safety and eliminates manual casting. Bounded type parameters restrict which types are allowed (extends for upper bound). Wildcards (?) represent unknown types — extends for reading, super for writing (PECS rule). Generics are implemented via type erasure — all type information is removed at runtime, making List<String> and List<Integer> the same class at runtime. Used everywhere in Java's Collections API and Spring Data JPA repositories."
Interview Questions & MAANG-Level Answers
Q1. What are generics and why were they introduced?
Generics allow classes, methods, and interfaces to be parameterized by type. Introduced in Java 5 to solve two problems: (1) Type safety — without generics, collections accepted any Object and ClassCastExceptions occurred at runtime. With generics, type errors are caught at compile time. (2) Eliminate casting — list.get(0) returns the typed String directly without (String) cast. Third benefit: code reuse — one Box<T> works for any type instead of writing BoxString, BoxInteger etc.
Q2. What is type erasure?
Type erasure is the process by which the Java compiler removes all generic type information after compilation. List<String> becomes List, Box<T> becomes Box. The compiler inserts appropriate casts automatically. Consequences: (1) Cannot create new T[] — type unknown at runtime. (2) list instanceof List<String> is illegal — no type info at runtime. (3) List<String>.class doesn't exist — only List.class. (4) Overloading methods by generic type only is impossible since signatures are identical after erasure.
Q3. What is the difference between <T extends Number> and <? extends Number>?
<T extends Number> is a bounded type parameter — T is a named type that can be referred to throughout the method/class: T get(T input) { return input; }. <? extends Number> is a bounded wildcard — anonymous type, cannot refer to it by name. Use T when you need to use the type multiple times in signatures. Use ? when you just need to accept a variety of types without referring to the specific type.
Q4. What is the PECS rule?
PECS = Producer Extends, Consumer Super. When a collection PRODUCES (you read from it) → use <? extends T>. When a collection CONSUMES (you write to it) → use <? super T>. Example: Collections.copy(List<? super T> dest, List<? extends T> src) — src produces elements (extends), dest consumes them (super). <?> (unbounded) when you only call methods available on Object.
Q5. Why can't you use primitive types with generics?
Generics work with Objects only — primitives (int, double, char etc.) are not Objects. List<int> is a compile error. Use wrapper classes instead: List<Integer>, List<Double>. Autoboxing/unboxing happens automatically: list.add(5) autoboxes 5 to Integer. Performance note: heavy use of generics with primitives causes autoboxing overhead — for performance-critical code with large primitive arrays, consider primitive arrays or specialized libraries.