Let's jump straight to the example:
import java.io.IOException;
import java.util.List;
import java.util.Optional;
public class Main {
static class GenericClass<UNUSED> {
private List<String> someList = List.of("Hello world!");
public Optional<String> getElement() {
return someList.stream().findFirst();
}
}
public static void generalMethod(GenericClass instance) {
instance.getElement().ifPresent(string -> { // <-- type info is lost here
// gives error because "string" variable is assumed to be Object
System.out.println(string.substring(0, 5));
});
}
public static void main(String[] args) throws IOException {
GenericClass<String> instance = new GenericClass<>();
generalMethod(instance);
}
}
Here we have a class with an unused generic. It has one method with explicitly specified return type of Optional<String>
. I'd expect this method to preserve the type information on return value so that in generalMethod
I can use substring
on returned String even when instance
argument there has unspecified generic type.
Yet there is a compile error:
/Main.java:18: error: cannot find symbol
System.out.println(string.substring(0, 5));
^
symbol: method substring(int,int)
location: variable string of type Object
Note: /Main.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
Question: Why does the absence of generic type on class instance lead to type information loss even for methods with hardwritten return types?
Side note: the error is gone if I write my argument as GenericClass<?>
or with any other generic type.
Java version: 11.0.4.