Java Reference
In-Depth Information
A raw type is like its parameterized counterpart, but all its instance members are replaced by their
erased counterparts. In particular, each parameterized type appearing in an instance method
declaration is replaced with its raw counterpart [JLS 4.8]. The variable p in our program is of the
raw type Pair , so its instance methods are erased. This includes the stringList method, which is
declared to return List<String> . The compiler interprets the program as if this method returned
the raw type List .
While List<String> implements the parameterized type Iterable<String> , List implements the
raw type Iterable . Where Iterable<String> has an iterator method that returns the
parameterized type Iterator<String> , Iterable has an iterator method that returns the raw type
Iterator . Where the next method of Iterator<String> returns String , the next method of
Iterator returns Object . Therefore, iterating over p.stringList() requires a loop variable of type
Object , which explains the compiler's bizarre error message. The reason this behavior is so
counterintuitive is that the parameterized type List<String> , which is the return type of the
stringList method, has nothing to do with the type parameter of Pair , but it gets erased anyway.
You could attempt to fix the problem by changing the type of the loop variable from String to
Object :
// Don't do this; it doesn't really fix the problem!
for (Object s : p.stringList())
System.out.print(s + " ");
This does cause the program to generate the expected output, but it doesn't really fix the problem.
You lose all the benefits of generics, and the program wouldn't even compile if the loop invoked
any String methods on s . The right way to fix the program is to provide a proper parameterized
declaration for the local variable p :
Pair <Object> p = new Pair<Object>(23, "skidoo");
This underscores a key point: The raw type List is not the same as the parameterized type
List<Object> . If the raw type is used, the compiler has no idea whether there are any restrictions
on the type of elements permitted by the list, but it lets you insert elements of any type. This is not
typesafe: If you insert an object of the wrong type, you may get a ClassCastException at any point
in the future execution of the program. If the parameterized type List<Object> is used, the
compiler knows that the list is allowed to contain elements of all types, so it is safe to let you insert
any object.
There is a third type that is closely related to these two: List<?> is a special kind of parameterized
type known as a wildcard type. Like the raw type List , the compiler does not know what type of
 
 
Search WWH ::




Custom Search