Java Reference
In-Depth Information
element is permitted, but because List<?> is a parameterized type, the language requires stronger
type-checking. To avoid the possibility of a ClassCastException , the compiler won't let you insert
any element except null into a list of type List<?> .
Raw types are a concession to existing code, which could not use generics prior to release 5.0.
Many core library classes, such as collections, have been modified to take advantage of generics,
but existing clients of those classes continue to behave as in previous releases. The behavior of raw
types and their members was designed to mirror the pre-5 language, so as to retain compatibility.
The real problem with the Pair program is that the author did not decide what version of Java to
use. Although most of the program uses generics, the variable p is declared with a raw type. To
avoid bewildering compile-time errors, avoid writing raw types in code intended for release 5.0
or later. If an existing library method returns a raw type, store its result in a variable of an
appropriate parameterized type. Better yet, upgrade to a version of the library that use generics, if
possible. Although Java provides graceful interoperability between raw and parameterized types,
limitations of raw types can interfere with the utility of generics.
This issue can arise in practice when reading Class annotations at run time with the
getAnnotation method, which was added to class Class in release 5.0. Two Class objects are
involved in each invocation of getAnnotation : the object on which the invocation is made and the
object that is passed to indicate which annotation is desired. In a typical invocation, the former is
obtained reflectively; the latter is a class literal, as in the following example:
Author a = Class.forName(name).getAnnotation(Author.class);
You do not have to cast the return value from getAnnotation to Author . Two things conspire to
make this work: (1) The getAnnotation method is generic. It infers its return type from its
parameter type. Specifically, it takes a parameter of type Class<T> and returns a value of type T . (2)
Class literals provide generic type information. For example, the type of Author.class is
Class<Author> . The class literal conveys both run-time and compile-time type information. Class
literals used in this fashion are known as type tokens [Bracha04] .
In contrast to class literals, Class objects obtained through reflection do not provide full generic
type information: The return type of Class.forName is the wildcard type Class<?> . It is critical that
you use this wildcard type rather than the raw type Class for the expression on which you invoke
the getAnnotation method. If you use the raw type, the returned annotation will have the compile-
time type of Annotation instead of the type indicated by the class literal. The following program
fragment, which violates this advice, won't compile for the same reason that the original program in
this puzzle did not:
Class c = Class.forName(name); // Raw type!
Author a = c.getAnnotation(Author.class); // Type mismatch
 
 
Search WWH ::




Custom Search