String gets assigned to a List without a compilation error [duplicate]

As I know, one of the main purposes of generics in Java is providing compile-time type safety. If it gets compiled, the code will run without issues.

Then why is the following code being compiled?

public static void main(String[] args) {
    String s = getList();
}

private static <T extends List> T getList() {
    return (T)new ArrayList();
}

It compiles fine. Where is my type-safe compilation? The getList() method has nothing in common with the String class.


Solution 1:

This is not a type erasure problem per se, but almost the opposite: You get a problem at runtime, when the system knows the actual types, but not at compile time. The reason why this compiles is that List is an interface. As far as the compiler is concerned, a subclass of String might actually implement that interface, so the compiler reasons that there could be valid runtime situations where the actual object returned is a String that is also a List. The compiler does not consider that String is final, and thus that it's impossible to actually create a List-implementing String class.

As to why final is not considered during compilation, Bohemian's comment to the question gives a good explanation.