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
to ArrayList
, 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).