Interview Prep Zoneby CuriouserLabs

Question 1 of 5 · senior level

What is type erasure? What are its practical consequences, and why did Java choose it?

🎤 Say this first

Generics are a compile-time discipline: after checking, the compiler erases type parameters to their bounds (TObject or the bound) and inserts casts at use sites. Chosen for backward/migration compatibility with pre-1.5 code. Consequences: no new T(), no T.class, no instanceof List<String>, one class object shared by all instantiations, overloads can clash after erasure, and unchecked casts can produce heap pollution that explodes far from the cause.

The full picture

What the compiler actually emits
List<String> names = new ArrayList<>();
names.add("a");
String s = names.get(0);

// After erasure (conceptually):
List names = new ArrayList();
names.add("a");
String s = (String) names.get(0);   // synthetic cast inserted

// Consequences:
names instanceof List<String>   // compile error — no runtime type
new T()                          // impossible — T doesn't exist at runtime
void f(List<String> l) {}
void f(List<Integer> l) {}       // clash: same erased signature
  • Workarounds seniors know: pass Class<T> tokens (T create(Class<T> type)), use super-type tokens (new TypeReference<List<Foo>>() {} — Jackson) which survive via getGenericSuperclass(), or Constructor<T> references.
  • Bridge methods: the compiler generates synthetic methods so overriding works across erased signatures — occasionally visible in stack traces and reflection.
  • Arrays vs generics: new T[10] is illegal; the idiom is (T[]) new Object[10] confined inside the class (as ArrayList does).

🔄 Likely follow-up questions

  • How does Jackson/Gson deserialize List<Order> despite erasure?
  • What is a bridge method and when would you actually encounter one?
  • What warnings does @SafeVarargs suppress and when is it honest to use it?