views:

371

answers:

2

I was taken aback earlier today when debugging some code to find that something like the following does not throw a compile-time exception:

 public Test () { 
  HashMap map = (HashMap) getList(); 
 }

 private List getList(){
  return new ArrayList();
 }

As you can imagine, a ClassCastException is thrown at runtime, but can someone explain why the casting of a List to a HashMap is considered legal at compile time?

+24  A: 

Because conceivably getList() could be returning a subclass of HashMap which also implements List. Unlikely, yes, but possible, and therefore compilable.

skaffman
+1: An explicit cast is basically a situation where the programmer is telling the compiler "I know what I'm doing, so do it my way" - if the compiler doesn't know that you're really really wrong, it will go your way. Well, that's one way that it was explained to me.
weiji
Yeah, the compiler should complain if you replace `List` with `ArrayList`.
Tom Hawtin - tackline
@weiji: That's only true to some extent, and far less true than it was in C or C++. The java compiler will only give you so much rope, and if A cannot possibly be an instance of B, it will not compile.
skaffman
Thanks. Looking at the JLS (http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5), it looks obvious after reading your explanation. It follows that final classes like `String` cannot be cast at compile-time, as there cannot potentially be a subclass which would implement `List`.
akf
+12  A: 

For one thing List is an interface. There is no reason why there couldn't exist a subclass of HashMap which also implements the List interface. In this situation it would be perfectly valid.

developmentalinsanity