D'accord, donc la surcharge de méthode est-une-mauvaise-chose™. Maintenant que cela a été réglé, supposons que je veuille vraiment surcharger une méthode comme ceci:
static void run(Consumer consumer) {
System.out.println("consumer");
}
static void run(Function function) {
System.out.println("function");
}
En Java 7, je pouvais les appeler facilement avec des classes anonymes non ambiguës en tant qu'arguments:
run(new Consumer() {
public void accept(Integer integer) {}
});
run(new Function() {
public Integer apply(Integer o) { return 1; }
});
Maintenant en Java 8, j'aimerais bien appeler ces méthodes avec des expressions lambda bien sûr, et je peux le faire!
// Consumer
run((Integer i) -> {});
// Function
run((Integer i) -> 1);
Étant donné que le compilateur devrait être capable d'inférer Integer
, pourquoi ne pas omettre Integer
, alors?
// Consumer
run(i -> {});
// Function
run(i -> 1);
Mais cela ne compile pas. Le compilateur (javac, jdk1.8.0_05) n'aime pas cela:
Test.java:63: erreur: référence à run est ambiguë
run(i -> {});
^
à la fois la méthode run(Consumer) dans Test et
la méthode run(Function) dans Test correspondent
Intuitivement pour moi, cela n'a pas de sens. Il n'y a absolument aucune ambiguïté entre une expression lambda qui renvoie une valeur ("compatible-valeur") et une expression lambda qui renvoie void
("compatible-void"), comme indiqué dans le JLS §15.27.
Mais bien sûr, le JLS est profond et complexe et nous héritons de 20 ans d'histoire de compatibilité ascendante, et il y a de nouvelles choses comme:
Certaines expressions d'argument contenant des expressions lambda implicitement typées (§15.27.1) ou des références de méthode inexacts (§15.13.1) sont ignorés par les tests de pertinence, car leur signification ne peut pas être déterminée avant qu'un type cible ne soit sélectionné.
La limitation ci-dessus est probablement liée au fait que JEP 101 n'a pas été mise en œuvre jusqu'au bout, comme on peut le voir ici et ici.
Question:
Qui peut me dire exactement quelles parties du JLS spécifient cette ambiguïté de compilation (ou s'agit-il d'un bug du compilateur)?
Bonus: Pourquoi les choses ont-elles été décidées de cette manière?