Я обнаружил странное сообщение об ошибке, которое, по моему мнению, может быть неверным. Рассмотрим следующий код:
public class Overloaded {
public interface Supplier {
int get();
}
public interface Processor {
String process(String s);
}
public static void load(Supplier s) {}
public static void load(Processor p) {}
public static int genuinelyAmbiguous() { return 4; }
public static String genuinelyAmbiguous(String s) { return "string"; }
public static int notAmbiguous() { return 4; }
public static String notAmbiguous(int x, int y) { return "string"; }
public static int strangelyAmbiguous() { return 4; }
public static String strangelyAmbiguous(int x) { return "string"; }
}
Если у меня есть метод, который выглядит следующим образом:
// Exhibit A
public static void exhibitA() {
// Genuinely ambiguous: either choice is correct
load(Overloaded::genuinelyAmbiguous); // <-- ERROR
Supplier s1 = Overloaded::genuinelyAmbiguous;
Processor p1 = Overloaded::genuinelyAmbiguous;
}
Ошибка, которую мы получаем, имеет смысл; параметру load() можно присвоить любой из них, поэтому мы получаем ошибку, в которой говорится, что вызов метода неоднозначен.
И наоборот, если у меня есть метод, который выглядит следующим образом:
// Exhibit B
public static void exhibitB() {
// Correctly infers the right overloaded method
load(Overloaded::notAmbiguous);
Supplier s2 = Overloaded::notAmbiguous;
Processor p2 = Overloaded::notAmbiguous; // <-- ERROR
}
Вызов load() в порядке, и, как и ожидалось, я не могу назначить ссылку на метод как для Supplier и для Processor потому что он не является неоднозначным: Overloaded::notAmbiguous не может быть назначено для p2.
А теперь странный. Если у меня есть такой метод:
// Exhibit C
public static void exhibitC() {
// Complains that the reference is ambiguous
load(Overloaded::strangelyAmbiguous); // <-- ERROR
Supplier s3 = Overloaded::strangelyAmbiguous;
Processor p3 = Overloaded::strangelyAmbiguous; // <-- ERROR
}
Компилятор жалуется, что вызов load() неоднозначен (error: reference to load is ambiguous), но, в отличие от приложения A, я не могу присвоить ссылку на метод как Supplier и Processor. Если бы это было действительно неоднозначно, я чувствовал бы, что я мог бы назначить s3 и p3 для обоих перегруженных типов параметров так же, как в Приложении A, но я получаю ошибку на p3 заявляющую, что error: incompatible types: invalid method reference. Эта вторая ошибка в Приложении C имеет смысл: Overloaded::strangelyAmbiguous не присваивается Processor, но если он не присваивается, почему он все еще считается неоднозначным?
Казалось бы, что вывод ссылки на метод только смотрит на арность FunctionalInterface при определении, какую перегруженную версию выбрать. В назначении переменной проверяется арность и тип параметров, что вызывает это несоответствие между перегруженным методом и назначением переменной.
Это кажется мне ошибкой. Если это не так, то, по крайней мере, сообщение об ошибке неверно, поскольку, возможно, нет никакой двусмысленности, когда между двумя вариантами верен только один.