简体   繁体   中英

Java weird compilation error with raw generic type parameter and Optionals

The following Java code doesn't compile (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 doesn't the code compile as above , and why does it compile if I change f1 to take a raw type:

static B<Integer> f1(B a) { return null; } // program compiles with raw B

My guess is that opt.map is inferred as returning Optional<Object> (instead of Optional<B<Integer>> ) but why? I have looked at other issues with generics and type erasure (JLS 4.8), but they all deal with the situation when a method is called on a raw type itself (eg this ). Here, opt is not raw, it only takes a raw type parameter. Also, why does the second version (where parameter a is raw B instead of B<Object> ) work?

Compilation Error Message

Error java: incompatible types: java.lang.Object cannot be converted to B<java.lang.Integer>

Make the f1 use a ? extends Object ? extends Object , add a 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();
    }
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM