Why do I need to explicitly specify type arguments when matching with Callable <T>?

When trying to answer another question, I found that my code only compiles if I explicitly give arguments of the type (no matter what the code calculates, it makes sense, I know):

public Double calculateResult(int value) { return 0.0d; } private void init2() { List<Callable<Double>> list = IntStream.range(1, 99) .<Callable<Double>>mapToObj(value -> (() -> calculateResult(value))) .collect(Collectors.toList()); } 

When deleting arguments of type <Callable<Double>> from mapToObj it does not compile and gives an error that it

cannot independently output a variable of type

It also cannot output arguments if I change it to use Supplier<Double> or DoubleSupplier .

Why can't it call type arguments?

Update , I am compiling it using Netbeans 8.0, have not tested it with the javac compiler yet.

+7
java generics lambda java-8 type-inference
source share
1 answer

This is my understanding of what is happening.

The problem is that you expect the compiler to use the expected destination type, in this case List<Callable<Double>> , to output type arguments. However .mapToObj not the last statement in the chain and does not return List .

This code below works because here the compiler can match the result of calling .mapToObj with what you declared as the return type, and therefore it can print the type arguments for the stream.

 Stream<Callable<Double>> temporaryVariable = IntStream.range(1, 99) .mapToObj(value -> (() -> calculateResult(value))); List<Callable<Double>> list = temporaryVariable.collect(Collectors.toList()); 

Since this is not the last statement in the chain, if I were a compiler, I would really not want to go through all possible Stream<?> Values ​​(which is essentially a .mapToObj return .mapToObj ) to find one call that will correspond to the next call to return List<Callable<Double>> .

+5
source share

All Articles