I saw this in an answer to another question, in reference to shortcomings of the Java spec:
There are more shortcomings and this is a subtle topic. Check
Another interesting thing with this example is the method overloading. The combination of type widening and method overloading only working because the compiler has to make a decision of which method to choose. Consider the following example:
public static void hello(Collection x){
System.out.println("Collection");
}
public static void hello(List x){
System.out.println("List");
}
public static void main(String[] args){
Collection col = new ArrayList();
hello(col);
}
It doesn't use the run-time type which is List, it uses the compile-time type which is Collection and thus prints "Collection".
I encourage your to read Effective Java, which opened my eyes to some corner cases of the JLS.