4

I have the following code and javac is not able to select version of the overloaded get() method to use. Why not?

public class x {
    static <T> T get(Key<T> key, T defaultValue)
    {throw new UnsupportedOperationException();}

    static <T> T get(Key<T> key,
            java.util.function.Supplier<T> defaultValueSupplier)
    {throw new UnsupportedOperationException();}

    static void test(){
        Key<String> k = new Key<>();
        String s = get(k, () -> "test");
    }

    private static class Key<T>{}
}

When I compile:

% javac -version
javac 1.8.0_202
% javac x.java
x.java:11: error: reference to get is ambiguous
        String s = get(k, () -> "test");
                   ^
  both method <T#1>get(Key<T#1>,T#1) in x and method <T#2>get(Key<T#2>,Supplier<T#2>) in x match
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>get(Key<T#1>,T#1)
    T#2 extends Object declared in method <T#2>get(Key<T#2>,Supplier<T#2>)
x.java:11: error: incompatible types: cannot infer type-variable(s) T
        String s = get(k, () -> "test");
                      ^
    (argument mismatch; String is not a functional interface)
  where T is a type-variable:
    T extends Object declared in method <T>get(Key<T>,T)
2 errors

The error is the same in Java versions 9-12.

My argument is that this line from the error is wrong:

both method <T#1>get(Key<T#1>,T#1) in x and method <T#2>get(Key<T#2>,Supplier<T#2>) in x match

The code does not match method <T#1>get(Key<T#1>,T#1) as k is of type Key<String> and the lambda is certainly not of type String.

If I change the code to:

Key<String> k = new Key<>();
Supplier<String> l = () -> "test";
String s = get(k, l);

then it works. What is causing javac to match the code against both methods?

Jesse
  • 3,751
  • 1
  • 21
  • 19

0 Answers0