Ambiguous method call when overloaded with generics and lambda

I noticed strange behavior for overload methods using generics and lambda. This class works fine:

  public <T> void test(T t) { }

  public <T> void test(Supplier<T> t) { }

  public void test() {
    test("test");
    test(() -> "test");
  }

There is no ambiguous method call. However, changing this parameter makes the second call ambiguous:

  public <T> void test(Class<T> c, T t) { }

  public <T> void test(Class<T> c, Supplier<T> t) { }

  public void test() {
    test(String.class, "test");
    test(String.class, () -> "test"); // this line does not compile
  }

How can it be? Why does adding another argument lead to ambiguity in the resolution of the method? Why can he indicate the difference between the Provider and the object in the first example, but not the second?

Edit: Used 1.8.0_121. This is the complete error message:

error: reference to test is ambiguous
    test(String.class, () -> "test");
    ^
  both method <T#1>test(Class<T#1>,T#1) in TestFoo and method <T#2>test(Class<T#2>,Supplier<T#2>) in TestFoo match
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>test(Class<T#1>,T#1)
    T#2 extends Object declared in method <T#2>test(Class<T#2>,Supplier<T#2>)
/workspace/com/test/TestFoo.java:14: error: incompatible types: cannot infer type-variable(s) T
    test(String.class, () -> "test");
        ^
    (argument mismatch; String is not a functional interface)
  where T is a type-variable:
    T extends Object declared in method <T>test(Class<T>,T)
+6
source share
2 answers

15 18 JLS Java SE 8 , 15.12.2:

, - (§15.27.1) (§15.13.1), , , .

Java , test(() -> "test"), () (.. ) , . <T> void test(T), <T> void test(Supplier<T>) w.r.t. test(() -> "test"). , , . , ( JLS 15.12.2.5 JLS 18.5.4) , 15.12.2.5:

, , , , , , .

<T> void test(Supplier<T>) T <T> void test(T), , .

, <T> void test(Class<T>, Supplier<T>), <T> void test(Class<T>, T) test(String.class, () -> "test"), , . , , . ., , JLS 18.5.1:

, C, .

...

  • :

k ≠ n (1 ≤ ≤ n) , e_i (§15.12.2.2) (...) , C (1 ≤ ≤ k), e_i , .

  • :

k ≠ n, , .

C (1 ≤ ≤ k), e_i , .

JLS 15.12.2.2:

m, :

  • - (§15.27.1).

...

, lambdas, , .

, , , - - , . , <T> void test(Class<T>, Supplier<T>), <T> void test(Class<T>, T), .

, test(String.class, (Supplier<String>) () -> "test"); , @Aominè . (Supplier<String>) () -> "test") - , , , , .

+1

.

JLS, .

, :

test(Callable.class, () -> new Callable() {

    @Override
    public Object call() throws Exception {
        return null;
    }

});

public <T> void test(Class<T> c, T t) 
same as below >> 
public <Callable> void test(Class<Callable> c, Callable<Callable> t)

- @FunctionalInterface,

public <T> void test(Class<T> c, Supplier<T> t)
same as below >>
public <Callable> void test(Class<Callable> c, Supplier<Callable> t)

- @FunctionalInterface,

, FunctionalInterface, , , , .

:

, :

test(() -> new Callable() {

    @Override
    public Object call() throws Exception {
        return null;
    }

})

public <T> void test(T t)

@FunctionalInterface, , .

public <T> void test(Supplier<T> t)

@FunctionalInterface, @FunctionalInterface (),

, Object , Object FunctionalInterface

, - JLS-, , , .

0

All Articles