Because some type information is erased during compilation, not all types are available at runtime. Types that are completely available at runtime are known as reifiable types.
- A primitive type
- A nonparameterized class or interface type
- A parameterized type in which all type arguments are unbounded wildcards
- A raw type
- An array whose component type is reifiable
Not reifiable types include:
- A type variable
- A parameterized type with actual parameters
- A parameterized type with a bound
Not reifiable types have some limitations:
- Can't be used for instance testing
- Cast to not reifiable type usually issues a warning
- The type must be reifiable to be used in catch statements or to extends Throwable
- Creation of array instance requires reifiable type
- Varargs should be of a reifiable type
An example of not reifiable types usage is an inability to use such types for instance creation:
class GenericClass<T> {
public GenericClass(T field) {
T t = new T(); // compile-time error: Cannot instantiate the type T
}
}
This limitation is reasonable since we have no way to guarantee that T will implement any particular constructor.Another limitation includes instance testing:
class GenericClass<T> {
public GenericClass(T field) {
boolean isInt = new Integer(0) instanceof T; // compile-time error:
// cannot perform instance check against type parameter T
}
}
Instance testing is unavailable since for non-reifiable types the information on exact type is unavailable at runtime.