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