0

I am registering a callable and saving it into a future object like this:

final Future<SomeObject> objectFuture= Executors.newFixedThreadPool(5).submit(
                    () -> methodReturnsSomeObject(someValue));

I am getting the following compilation error but its building locally:

[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /c:/1/5889/001/target/clover/src/com/... reference to submit is ambiguous

both method submit(java.util.concurrent.Callable) in java.util.concurrent.ExecutorService and method submit(java.lang.Runnable) in java.util.concurrent.ExecutorService match

This happens when there are ambiguity in overloaded methods e.g. Integer... and int... according to Compiler error : reference to call ambiguous. I do not see why its showing this here. I am clearly passing a Callable here in the above method. Please let me know how it is ambiguous? Also, since my maven build is passing locally and not in Jenkins, do I need to look at the Jenkins server configuration? Thanks in advance

Java version: 1.8 Maven Version: 3.0.5

Siddharth Shankar
  • 489
  • 1
  • 10
  • 21

1 Answers1

2

submit() has 2 overloads with one argument. The arguments are both functional interfaces, with the following methods:

Your lambda expression is () -> methodReturnsSomeObject(someValue).

If the method hadn't returned anything, i.e. was a void method, it could only implement Runnable, so there would have been no ambiguity.

But since the method has a return value matching type T (SomeObject in your case), the lambda expression can implement Callable, but it can also implement Runnable by ignoring/discarding the return value. Having it implement Callable is of course preferable.

Be aware that some compilers will resolve to Callable, especially newer versions of the compiler, which will have improved inference handling, so you will not always experience this issue.

To resolve an ambiguity, cast to the parameter type you desire. In this case, we desire Callable, so:

final Future<SomeObject> objectFuture = Executors.newFixedThreadPool(5).submit(
                    (Callable<SomeObject>) () -> methodReturnsSomeObject(someValue));
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • Thanks @Andreas, that explains it. One follow up, in my local I have Java 8 and maven and same Java and maven configuration in Jenkins. What could be the reason apart from java and maven its building locally? – Siddharth Shankar Dec 17 '20 at 06:12
  • 1
    @SiddharthShankar Different versions of Java, of the Java compiler? – Andreas Dec 17 '20 at 07:08
  • 2
    You can enforce `Callable` or `Runnable` by using dedicated brackets: `() -> (methodReturnsSomeObject(someValue))` will never be a `Runnable`, as an expression in brackets is not a statement. And `() -> { methodReturnsSomeObject(someValue); }` will never be a `Callable`, as it has no `return`. – Holger Dec 18 '20 at 11:51