Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java compilation fail with method reference but works with lambda

We're trying to add an overloaded collect method to our extended Java Stream API which we're currently defining as:

interface ExtendedStream<R> extends Stream<R> {

   <R1> R1 collect(SerializableSupplier<Collector<? super R, ?, R1>> supplier);

}

SerializableSupplier is define as just:

interface SerializableSupplier<T> extends Serializable, Supplier<T> {
}

Calling this collect method with a lambda works fine, but calling it with a method reference fails to compile with errors such as:

Error:(50, 72) java: incompatible types: cannot infer type-variable(s) R1,capture#1 of ?,T
    (argument mismatch; bad return type in method reference
      java.util.stream.Collector<T,capture#1 of ?,java.util.List<T>> cannot be converted to java.util.stream.Collector<? super java.util.Map.Entry<java.lang.Integer,java.lang.String>,?,R1>)

I've created a standalone Java class here which you can load into your compiler to try it out.

I'm currently using Java version:

java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

Is this is a bug or some error in how we're defining things?

NOTE: I get this compilation error both from IntelliJ and when compiling with Maven. I don't use Eclipse.

Cheers, Galder

like image 334
Galder Zamarreño Avatar asked Sep 18 '17 08:09

Galder Zamarreño


1 Answers

This is a bug in javac 8 as it compiles just fine with javac-9 (with the latest build) - I just can't find it and I really really tried to.

Almost as usual adding more type information fixes such things... Also notice that I've changed your Comparator to Comparator.comparingInt...:

 return entrySet.stream().sorted(
            Comparator.comparingInt(Entry::getKey)).collect(
                    Collectors::<Map.Entry<Integer, String>> toList); 
like image 187
Eugene Avatar answered Oct 16 '22 12:10

Eugene