I know that similar type inference questions have been posted before (Java compiler choosing wrong overload or Why does the Java 8 generic type inference pick this overload?) but I think we picked a more interesting case here.
public class TemplateMethod {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
method("a", "b");
method("a", 5);
method("a", new B().get());
}
public static void method(String s, String cause) {
System.out.println("String");
}
public static void method(String s, Object parameters) {
System.out.println("Object");
}
public static interface Base {
String methodToImplement();
}
public static class Impl implements Base {
public String methodToImplement() {
return "Impl.methodToImplement";
}
}
public static class B {
public <T extends Base> T get() {
return (T) new Impl();
}
}
}
The output is:
Exception in thread "main" java.lang.ClassCastException:
TemplateMethod$Impl cannot be cast to java.lang.String at
TemplateMethod.main(TemplateMethod.java:9)
What I cannot understand here, that if the return type is T extends Base
how can String
be candidate for the return type?
The previous questions on StackOverflow do not deal with the special case with generics like here so I think this is not a duplicate. At those cases mentioned above the Java8 compiler behaves as the language specification is written. In this case I think that is not the case, the signature method(String, String)
should not need to be considered for the return type of T <T extends Base>
since a String
will never be a TemplateMethod.Base
defined here.