Why does Java let you cast to a collection? [duplicate]
Solution 1:
It's not because they're collection classes, it's because they're interfaces. Foo
doesn't implement them, but subclasses of it could. So it's not a compile-time error, since those methods may be valid for subclasses. At runtime, if this
isn't of a class that implements those interfaces, naturally it's a runtime error.
If you change List<String>
to ArrayList<String>
, you'll get a compiler-time error for that, too, since a Foo
subclass could implement List
, but can't extend ArrayList
(since Foo
doesn't). Similarly, if you make Foo
final
, the compiler will give you an error for your interface casts because it knows they can never be true (since Foo
can't have subclasses, and doesn't implement those interfaces).
Solution 2:
The compiler doesn't prevent code from casting a type to an interface, unless it can establish for sure that the relationship is impossible.
If the target type is an interface, then it makes sense because a class extending Foo
can implement Map<String, String>
. However, note that this only works as Foo
is not final
. If you declared your class with final class Foo
, that cast would not work.
If the target type is a class, then in this case it would simply fail (try (HashMap<String, String>) this
), because the compiler knows for certain that the relationship between Foo
and HashMap
is impossible.
For reference, these rules are described in JLS-5.5.1 (T = target type - Map<String, String>
, S = source type - Foo
)
If T [target type] is an interface type:
If S is not a final class (§8.1.1), then, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types, and that the erasures of X and Y are the same, a compile-time error occurs.
Otherwise, the cast is always legal at compile time (because even if S does not implement T, a subclass of S might).If S is a final class (§8.1.1), then S must implement T, or a compile-time error occurs.
Note the bold-italic comment in the quoted text.