In Java, the type of an array is reified with its component type, while the type of a parameterized type is reified without its type parameters. For instance, an array of numbers will carry the reified type Number, while a list of numbers will carry the reified type ArrayList, not ArrayList<Number>; the raw type, not the parameterized type, is reified. Of course, each element of the list will have a reified type attached to itsay Integer or Doublebut this is not the same as reifying the parameter type. If every element in the list was an integer, we would not be able to tell whether we had an ArrayList<Integer>, ArrayList<Number>, or ArrayList<Object>; if the list was empty, we would not be able to tell what kind of empty list it was.
In Java, we say that a type is reifiable if the type is completely represented at run time that is, if erasure does not remove any useful information. To be precise, a type is reifiable if it is one of the following:
A type is not reifiable if it is one of the following:
So the type List<? extends Object> is not reifiable, even though it is equivalent to List<?>. Defining reifiable types in this way makes them easy to identify syntactically.