Section 7.2. Reflected Types are Reifiable Types


7.2. Reflected Types are Reifiable Types

Reflection makes reified type information available to the program. Of necessity, therefore, each class token corresponds to a reifiable type. If you try to reflect a parameterized type, you get the reified information for the corresponding raw type:

 List<Integer> ints = new ArrayList<Integer>(); List<String> strs  = new ArrayList<String>(); assert ints.getClass() == strs.getClass(); assert ints.getClass() == ArrayList.class; 

Here the type list of integers and the type list of strings are both represented by the same class token, the class literal for which is written ArrayList.class.

Because the class always represents a reifiable type, there is no point in parameterizing the class Class with a type that is not reifiable. Hence, the two main methods for producing a class with a type parameter, namely the getClass method and class literals, are both designed to yield a reifiable type for the type parameter in all cases.

Recall that the getClass method is treated specially by the compiler. In general, if expression e has type T, then the expression e.getClass() has type Class<? extends |T|>, where |T| is the erasure of the type T. Here's an example:

 List<Integer> ints = new ArrayList<Integer>(); Class<? extends List> k = ints.getClass(); assert k == ArrayList.class; 

Here the expression ints has type List<Integer>, so the expression int.getClass() has type Class<? extends List>; this is the case because erasing List<Integer> yields the raw type List. The actual value of k is ArrayList.class, which has type Class<ArrayList>, which is indeed a subtype of Class<? extends List>.

Class literals are also restricted; it is not even syntactically valid to supply a type parameter to the type in a class literal. Thus, the following fragment is illegal:

 class ClassLiteral {   public Class<?> k = List<Integer>.class;  // syntax error } 

Indeed, Java's grammar makes a phrase such as the preceding one difficult to parse, and it may trigger a cascade of syntax errors:

 % javac ClassLiteral.java ClassLiteral.java:2: illegal start of expression   public Class<?> k = List<Integer>.class;  // syntax error                                    ^ ClassLiteral.java:2: ';' expected   public Class<?> k = List<Integer>.class;  // syntax error                                     ^ ClassLiteral.java:2: <identifier> expected   public Class<?> k = List<Integer>.class;  // syntax error                                          ^ ClassLiteral.java:4: '}' expected ^ 4 errors 

The parser has so much trouble with this phrase that it is still confused when it reaches the end of the file!

This syntax problem leads to an irregularity. Everywhere else that a reifiable type is required, you may supply either a raw type (such as List) or a parameterized type with unbounded wildcards (such as List<?>). However, for class tokens, you must supply a raw type; not even unbounded wildcards may appear. Replacing List<Integer> with List<?> in the preceding code leads to a similar error cascade.

The restrictions on class tokens lead to a useful property. Wherever a type of the form Class<T> appears, the type T should be a reifiable type. The same is true for types of the form T[].




Java Generics and Collections
Java Generics and Collections
ISBN: 0596527756
EAN: 2147483647
Year: 2006
Pages: 136

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net