As Bohemian said, every type argument in a raw type is thrown away. At the beginning I thought it was a bug, but there's even an entry in the bug database (#6244346) which explicitely quotes the relevant JLS §4.8
The type of a constructor (§8.8), instance method (§8.4, §9.4), or
non-static field (§8.3) M 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.
The type of a static method or static field of a raw type C is the
same as its type in the generic declaration corresponding to C.
It is a compile-time error to pass type arguments to a non-static type
member of a raw type that is not inherited from its superclasses or
superinterfaces.
It is a compile-time error to attempt to use a type member of a
parameterized type as a raw type.
The reason why you can't get a String
from a raw List
, but you can assign a List
to a List<String>
is because in the latter the compiler issues a warning (unchecked conversion) but you don't report it (do you read warnings, don't you? :P). I tested your code with javac and the Eclipse compiler, and both honor the spec.
Raw types were introduced for interoperability with legacy code, but in this case I can't figure out a way how keeping type information for non-static members would have break things. Using a parameterized type instead of a raw type would mean code partially ported, so maybe in this case the purpose is not simply backcompat, but ensuring a coherent codebase, either the code is full 1.4, or it's entirely Java 5+. Another option is that using raw types like this may have slowed down the adoption of unbounded wildcards in similar contexts.
BTW (but I think you figured it out by yourself) you can simply use an unbounded wildcard if you don't use the type parameter, ie Container<?>