Java Reference
In-Depth Information
Another thing to watch out for when using generic types are compiler warnings.
They may indicate that you're doing something that is not recommended and it usually
indicates that your code has a potential runtime error looming. An example can help to
illustrate this. The following code will compile but produce two compiler warnings:
List rawList = new LinkedList();
aList = rawList;
First, you're creating
rawList
, which is a
raw type
, a generic type that isn't para-
meterized. When generics were introduced into the language, the language designers
decided that in order to maintain compatibility with pregenerics code, they would need
to allow the use of raw types. However, the use of raw types is strongly discouraged for
newer (post-Java 5) code, so compilers will generate a raw type warning if you use
them. Next,
rawList
is assigned to
aList
, which was created using parameterized
types. Again, this is allowed by the compiler (due to generics type erasure and back-
ward compatibility), but an unchecked conversion warning is generated for the assign-
ment to flag potential runtime type incompatibility. Imagine if
rawList
contained
Strings
. Later, if you tried to retrieve
Integer
elements from
aList
, you would
get a runtime error.
Regarding type compatibility, it doesn't apply to generic type parameters. For ex-
ample, the following is not a valid assignment:
List<Number> bList = new LinkedList<Integer>(); // won't
compile; incompatible types
Although
Integers
are
Numbers
(
Integer
is a subtype of
Number
), and
LinkedList
is a subtype of
List
,
LinkedList<Integer>
is not a subtype of
List<Number>
. Fortunately, this won't slip by you if you accidentally write code
like this; the compiler will generate an “incompatible types” warning.
So you may be wondering whether there is a way to achieve a variant subtyping re-
lationship similar to what we tried to do in the previous line of code. The answer is yes,
by using a feature of generics called the
wildcard
. A wildcard is denoted by use of a
question mark (
?
) within the type parameter angle brackets. Wildcards are used to de-
clare parameterized types that are either bounded or unbounded. The following is an
example declaration of a bounded parameterized type:
List<? extends Number> cList;