Я обнаружил странное сообщение об ошибке, которое, по моему мнению, может быть неверным. Рассмотрим следующий код:
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 при определении, какую перегруженную версию выбрать. В назначении переменной проверяется арность и тип параметров, что вызывает это несоответствие между перегруженным методом и назначением переменной.
Это кажется мне ошибкой. Если это не так, то, по крайней мере, сообщение об ошибке неверно, поскольку, возможно, нет никакой двусмысленности, когда между двумя вариантами верен только один.