Java Compile Error: Method reference in combination with overloading

匆匆过客 提交于 2019-12-05 02:06:31

Well, we can simplify this:

// takes a Runnable
public static void doStuff(Runnable runable) {
    System.out.println("Runnable");
}

// takes a Callable
public static void doStuff(Callable<List<String>> callable) {
    System.out.println("Callable");
}

And two extra methods that are overloads.

private static List<String> go() {
    return null;
}

private static List<String> go(int i) {
    return null;
}

What do you think will happen if you call this:

doStuff(YourClass::go);

Yeah... this will fail to match. And you might think that this is stupid as it only makes sense that go is the one that takes no arguments, it is easy for you in this simple situation to make this judgment, it's not for the compiler. In essence this is like a dead-lock:

In order to know which doStuff method to call, we need to know which go to call; and at the same time to understand which go to call we need to know which doStuff to call, or:

we need to resolve the method in order to find the target type, but we need to know the target type in order to resolve the method.

Same thing happens in your case with ArrayList having more than one constructors...

But how does the compiler decide which of the two methods is executed in test2?

public void test2 () {
    doStuff ( () -> new ArrayList<> ());
}

is implicitly

public void test2 () {
    doStuff ( () -> { return new ArrayList<>(); } );
}

and only Callable returns an object.

Why can I use the lambda expression but not the method reference?

It could be

public void test2 () {
    doStuff ( () -> { new ArrayList<>(); } );
}

EDITED

Look at those examples:

Runnable r = ArrayList::new; // compiled
Callable c = ArrayList::new; // compiled
doStuff(ArrayList::new); // compile error, ambiguous

So ArrayList::new is interpreted as both Runnable and Callable. Note there is no lambda involved.

Next example:

Runnable r = () -> new ArrayList<>(); // compiled
Callable c = () ->  new ArrayList<>(); // compiled
doStuff(() -> new ArrayList<>()); // compiled, the Callable one

When passing () -> new ArrayList<>() to a method

() -> { return new ArrayList<>(); }

is preferred than

() -> { new ArrayList<>(); }

So, the Callable one is invoked and there is nothing ambiguous.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!