Strange compilation errors for Java generic type parameters and optionals
The following java code cannot be compiled (using javac 1.8.0_121)
import java.util.Optional; class B<T> {} public class Test { static B<Integer> f1(B<Object> a) { return null; } static B<Integer> f2() { Optional<B> opt = Optional.empty(); // note the raw type B return opt.map(Test::f1).get(); // error: incompatible types: Object cannot be converted to B<Integer> } }
My question is: why can't the code compile as above? If I change F1 to get the original type, why does it compile
static B<Integer> f1(B a) { return null; } // program compiles with raw B
My guess is opt Map is inferred to return optional < Object > (instead of optional < B < integer > >), but why? I've looked at other issues with generics and type erasure (JLS 4.8), but they both deal with situations when methods are called on the original type itself (such as this) Here, opt is not primitive, it only needs a primitive type parameter In addition, why is the second version (parameter a is original B instead of B < Object >) valid?
Compile error message
Error: incompatible type: Java Lang.Object cannot be converted to B < Java lang.Integer>
Solution
Let F1 use? Extends object to add the wildcard type to B
import java.util.Optional; class B<T> {} public class Test { static B<Integer> f1(B<? extends Object> a) { return null; } static B<Integer> f2() { Optional<B<?>> opt = Optional.empty(); // note the raw type B return opt.map(x -> f1(x)).get(); } }