When using Foo t
, t
is a Raw Type so its non-static, non-inherited members, like the list
in above code, are also raw types. Here the relevant part of the Java Language Specification (see above link):
To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.
More precisely, a raw type is defined to be one of:
and/or
The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C.
Just declare the list
as static
and it will be interpreted as a List
of String
as expected (for testing).
On the other side, the declaration Foo<?>
is not a raw type and consequently the list
is also not considered a raw type.
An advice later on that page:
The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of generics into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.
Note: Type Erasure and generated byte-code is the same in both cases...