What does it mean for a type to be 'reifiable' in Java, and which generic types are reifiable?
answer
- Reifiable = full type info survives to runtime
- Raw + unbounded-wildcard + non-generic = reifiable
- List<String> and bounded wildcards = NOT reifiable
- Gates instanceof, array creation, unchecked casts
- JLS §4.7
basics
~20 sA reifiable type is one whose full type information is still available at runtime. Plain types, raw types, and unbounded wildcards like List<?> are reifiable; parameterized types like List<String> are not, because erasure throws the type argument away.
solid answer
~40 s'Reifiable' (from JLS §4.7) means a type is completely represented at runtime — nothing about it was lost to type erasure. Reifiable types include primitives, non-generic classes/interfaces, raw types (`List`), parameterized types where every argument is an unbounded wildcard (`List<?>`, `Map<?, ?>`), and arrays of reifiable types. Non-reifiable types are concrete parameterizations like `List<String>` and bounded wildcards like `List<? extends Number>`, because their type arguments don't survive erasure. Reifiability is the property that decides what's legal in runtime-sensitive constructs: only reifiable types may appear in `instanceof`, as array component types (`new String[]` ok, `new List<String>[]` not), and as the target of certain casts without an unchecked warning. So the `instanceof` restriction is just one consequence of a single underlying rule.
go deeper
Recognizes the word and that List<String> 'loses' its type at runtime, even if can't yet name the full reifiable set.
Defines reifiable as 'type info survives to runtime' and lists the common reifiable vs non-reifiable forms.
Cites JLS §4.7, enumerates the reifiable set precisely, and explains how reifiability gates instanceof, array creation, and unchecked casts.
Uses reifiability as a unifying lens to predict all erasure-driven restrictions and discusses how it interacts with heap pollution, generic varargs, and proposed (Valhalla) reified generics.
## What 'reify' means To **reify** something abstract is to make it a concrete, tangible thing. In Java's generics, **reifiable** is a precise JLS term (§4.7): a type is reifiable if **all of its information is available at runtime**, i.e. *nothing about it was erased*. ## Why this concept exists: type erasure Java generics are compile-time only. After the compiler type-checks your code, it **erases** type arguments so the bytecode looks the way it did before Java 5. `List<String>` becomes `List`; a type parameter `T` with no bound becomes `Object` (or its leftmost bound if it has one). The runtime therefore has **less** type information than the source did. A type is reifiable precisely when that erasure step removed *nothing*. ## The reifiable list (memorize this) A type is reifiable if it is one of: 1. A **primitive** (`int`, `double`, …). 2. A **non-generic** class or interface (`String`, `Runnable`). 3. A **raw type** (`List`, `Map`) — you're not asserting any argument. 4. A parameterized type where **every** argument is an **unbounded wildcard**: `List<?>`, `Map<?, ?>`, `Set<?>`. The `<?>` asserts nothing checkable, so no info is lost. 5. An **array** whose component type is reifiable: `String[]`, `int[]`, `List<?>[]`. 6. A nested type all of whose enclosing parts are reifiable. ## The NON-reifiable list - Concrete parameterizations: `List<String>`, `Map<String,Integer>`, `ArrayList<Long>`. - Bounded wildcards: `List<? extends Number>`, `List<? super Integer>`. - Type variables: `T`, `E`. All of these had real type information stripped by erasure, so the runtime cannot reconstruct or verify them. ## Why it matters — the rules reifiability gates Reifiability is not trivia; it is the single property the language uses to decide several restrictions: - **`instanceof`** may only use reifiable types. Hence `instanceof List<?>` is fine but `instanceof List<String>` is a compile error. - **Array creation** requires a reifiable component type. `new String[10]` and `new List<?>[10]` are legal; `new List<String>[10]` is a compile error ("generic array creation"). This is because arrays are **covariant and self-checking at runtime** (an `ArrayStoreException` is thrown if you store the wrong type), but they can only perform that runtime check against a reifiable component type. - **Casts** to non-reifiable types produce an *unchecked* warning, because the JVM cannot fully verify them — it can only check the erased form. - **Exceptions:** a generic class cannot directly or indirectly subclass `Throwable`, and you cannot `catch` a type variable, partly because catch clauses need reifiable types. ## Putting it together with `instanceof` The "no `instanceof List<String>`" rule is therefore *not a special case*. It falls straight out of: `instanceof` needs a reifiable operand, and `List<String>` isn't reifiable. The allowed `List<?>` is allowed for exactly one reason — `<?>` is reifiable. Understanding reifiability lets you predict every one of these restrictions instead of memorizing them individually.
- Why is `new List<String>[10]` illegal but `new List<?>[10]` legal?Array creation requires a reifiable component type because arrays do runtime store-checks (ArrayStoreException). `List<String>` is non-reifiable, so the array couldn't perform that check; `List<?>` is reifiable, so it's allowed.
- Is `List<?>[]` reifiable, and is `List<? extends Number>` reifiable?`List<?>[]` is reifiable (array of a reifiable type). `List<? extends Number>` is NOT reifiable — bounded wildcards carry bound information that erasure removes.
saying these in an interview costs you the question
- Saying List<String> is reifiable because getClass() returns ArrayList — that is the erased type, not the parameterization
- Claiming arrays of List<String> can be created (generic array creation is illegal)
- Confusing reifiable with 'final' or 'concrete'
- Thinking bounded wildcards are reifiable like unbounded ones