THE Java™ Programming Language, Fourth Edition

(Jeff_L) #1

A.3. Generics: Reification, Erasure, and Raw Types


The generic type system was added to the Java programming language for the 5.0 release. The design was
strongly constrained by the need to maintain compatibility between independently developed code modules
that may or may not include the use of generics. The key design decision was that generic types could not be
reified at runtime. Rather, for each generic type declaration there would be a single type that was defined in
terms of the erasure of its type variables. As we discussed in Chapter 11, in simple terms the type is defined
such that each type variable is replaced by its boundcommonly Object. The reasoning behind this decision
is beyond the scope of this book, but to quote JLS 4.7 (The Java™ Language Specification, Third Edition,
Section 4.7):


...the design of the generic type system seeks to support migration compatibility. Migration
compatibility allows the evolution of existing code to take advantage of generics without
imposing dependencies between independently developed software modules. The price of
migration compatibility is that full reification of the generic type system is not possible, at
least while the migration is taking place.

Note that in the future, this design decision might be changed.


A.3.1. Raw Types, "Unchecked" Warnings, and Bridge Methods


A consequence of the reification design decision is the existence and use of raw types. Raw types represent
the erasure of a specific generic type. They exist so that code that was written to use a non-generic version of
a class or interface can execute in a virtual machine that uses a generic version of that class or interface. Some
of these uses may cause "unchecked" warnings to be issued by the compiler, but the uses are still permitted.
"Unchecked" warnings are emitted in the following circumstances:


Assignment from a raw type variable to a parameterized type variablethe raw type variable might not
refer to an instance of the expected parameterized type.


Casts involving type variablesthe cast cannot be checked at runtime because the erasure of the type
variable is used.



  • Invocation of a method or constructor of a raw type if erasure changes the type of a parameter.

  • Access to a field of a raw type if erasure changes the type of the field.


The conversion between a raw type and a parameterized type adds an additional conversion to those defined
in Section 9.4 on page 216: the unchecked conversion. These unchecked conversions can be applied as the
final step in most of the conversion contextsfor example, as part of an assignment. An unchecked conversion
is always accompanied by an "unchecked" warning, unless it has been suppressed by using the annotation
SuppressWarnings("unchecked")if your compiler supports this.


Use of raw types can also lead to other complications. Consider a variation of the passThrough example
from Chapter 11 repackaged as a generic interface:


interface PassThrough {
T passThrough(T t);
}


Now consider an implementation of that interface:


class PassThroughString implements PassThrough {
public String passThrough(String t) {
return t;
}

Free download pdf