Interview
Generics — Interview Questions (60+)
Detailed Questions
1. Why generics?
- Short: Compile-time type safety and fewer casts.
- Detailed: Generics let you parameterize types, catching type errors at compile time and removing explicit casts. They make APIs self-documenting and reusable.
- Example:
List<String>prevents adding an Integer.
2. What is type erasure?
- Short: Generic type info is removed at runtime.
- Detailed: The compiler erases type parameters to their bounds (or Object), inserting casts. So
List<String>andList<Integer>share one runtime class. Consequences: nonew T[], no runtimeinstanceof List<String>, no overloads differing only by type args. - Example:
list.getClass() == List.classregardless of<T>.
3. Explain PECS.
- Short: Producer Extends, Consumer Super.
- Detailed: Use
? extends Twhen you only READ Ts from a structure (it produces Ts). Use? super Twhen you only WRITE Ts into it (it consumes Ts). This maximizes flexibility. - Example:
copy(List<? super T> dst, List<? extends T> src).
4. Bounded type parameters?
- Short: Constrain
<T>to a supertype. - Detailed:
<T extends Number>lets you call Number methods and accept Number subtypes. Multiple bounds:<T extends A & B>(class first). - Example:
<T extends Comparable<T>> T max(List<T> xs).
5. Wildcards vs type parameters?
- Short: Wildcards for flexibility at use-site; type params to relate types.
- Detailed: Use a type parameter when multiple positions must be the same type or the return type depends on it. Use a wildcard for one-off flexibility without naming the type.
- Example:
void printAll(List<?> list)vs<T> T first(List<T> list).
6. Why can't you create a generic array?
- Short: Erasure makes array store checks unsound.
- Detailed:
new T[]is illegal because the runtime can't enforce the component type (arrays are reified, generics are erased). Workarounds:(T[]) new Object[n]with@SuppressWarnings, orArray.newInstance. - Example: Collections use
Object[]internally.
7. What is a generic method?
- Short: A method with its own type parameters.
- Detailed: Declared before the return type:
<T> T identity(T x). The compiler infersTfrom arguments. - Example:
Collections.<String>emptyList().
8. What is heap pollution?
- Short: A parameterized variable refers to an object of a different type.
- Detailed: Often via unchecked casts or varargs of generics; can cause
ClassCastExceptionlater.@SafeVarargssuppresses the warning when the method is provably safe. - Example: Mixing raw and generic types.
Rapid-Fire (Q → A)
- Diamond operator? →
<>infers type args. - Raw type? → Generic used without args (legacy).
ListvsList<Object>vsList<?>? → Raw / any-object / unknown-type.- Can you add to
List<?>? → Only null. - Can you add to
List<? extends Number>? → No (read-only producer). - Can you add to
List<? super Integer>? → Yes, Integers. - Upper bound syntax? →
? extends T. - Lower bound syntax? →
? super T. - Unbounded wildcard? →
?. - Multiple bounds order? → Class first, then interfaces.
- Generic class syntax? →
class Box<T> {}. - Generic interface? →
interface Repo<T> {}. - Generic method syntax? →
<T> T m(T x). - Bounded method? →
<T extends Number>. - Recursive bound? →
<T extends Comparable<T>>. - Type inference source? → Arguments/target type.
- Var with generics? → Infers full type.
- Erasure replaces T with? → Its bound or Object.
- instanceof with generics? → Only unbounded
List<?>. - Cast to generic warning? → Unchecked.
- SuppressWarnings("unchecked")? → Silence unchecked.
- Generic array creation? → Illegal.
- Varargs + generics? → Heap pollution warning.
- @SafeVarargs? → Asserts safe varargs.
- Static generic field? → Not allowed (no class type param in static).
- Generic exception? → Can't extend Throwable generically.
- Overload by type arg? → Not allowed (erasure).
- Bridge methods? → Synthetic methods for erasure/overriding.
- Reifiable type? → Type fully available at runtime.
- Non-reifiable type? → Erased generic type.
- Why no primitives in generics? → Only reference types; use wrappers.
- Generic + autoboxing cost? → Boxing overhead.
- Comparable
reason? → Self-type comparison. - Comparator generic? →
Comparator<? super T>. - Collections.sort signature? → Uses
? super Tcomparator. - PECS for Collections.copy? → dst super, src extends.
- Function<? super T,? extends R>? → Flexible function params.
- Wildcard capture? → Helper method infers the unknown type.
- Why capture helper? → To modify a
List<?>safely. - Generic constructor? →
<T> Box(T x). - Diamond with anonymous class? → Allowed (Java 9+).
- Type token? →
Class<T>to retain type. - Super type token? →
TypeReferencetrick for generics. - Generic singleton factory? →
Collections.emptyList(). - Covariance in arrays? → Arrays covariant (unsafe).
- Covariance in generics? → Invariant by default.
- Make generics covariant? → Use
? extends. - Contravariance? →
? super. - Invariance meaning? →
List<String>not aList<Object>. - Why generics invariant? → Type safety on writes.
- Self-referential generic? → CRTP-style bounds.
- Builder with generics? → Fluent typed builder.
- Generic enum? → Not allowed.
- Generic with bounds + multiple interfaces? →
<T extends A & B>. - Inferred return type? → From target/assignment.
- Generic default method? → Allowed.
- Erasure and reflection? → Some info via signatures.
- getGenericSuperclass? → Reflect parameterized supertype.
- Wildcard in return type? → Discouraged (hard to consume).
- Golden rule? → Use bounded wildcards on input params (PECS), exact types on outputs.