Je suis tombé sur cet extrait:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Cela entraînera une erreur de compilation:
Erreur: (15, 9) java: la référence à printSum est ambiguë à la fois la méthode printSum (int, double) dans ParamTest et la méthode printSum (long, long) dans la correspondance ParamTest
Comment est-ce ambigu? Ne devrait-on pas seulement promouvoir le deuxième paramètre dans ce cas puisque le premier paramètre est déjà un int? Le premier paramètre n'a pas besoin d'être promu dans ce cas, non?
La compilation réussit si je mets à jour le code pour ajouter une autre méthode:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Permettez-moi de développer juste pour clarifier. Le code ci-dessous crée une ambiguïté:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, long b) {
System.out.println("In long " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Ensuite, ce code ci-dessous entraîne également une ambiguïté:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(double a, long b) {
System.out.println("In doubleLONG " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
Cependant celui-ci n'entraîne pas d'ambiguïté:
public class ParamTest {
public static void printSum(int a, double b) {
System.out.println("In intDBL " + (a + b));
}
public static void printSum(long a, double b) {
System.out.println("In longDBL " + (a + b));
}
public static void main(String[] args) {
printSum(1, 2);
}
}
java
java-8
type-promotion
riruzen
la source
la source
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
- ce n'est pas la méthode qui est ambiguë, c'est l'appel à la méthode qui est ambiguë.Réponses:
Je pense que cela a quelque chose à voir avec la règle spécifique de JLS concernant le 15.12.2.5. Choisir la méthode la plus spécifique . Il déclare que:
Comment Java choisit la méthode la plus spécifique est expliqué plus en détail dans le texte:
Dans le cas de votre exemple, toutes les méthodes sont accessibles et applicables à l'appel de méthode, par conséquent, Java doit déterminer laquelle est la plus spécifique .
Pour ces méthodes, aucune ne peut être considérée comme plus spécifique:
La quatrième méthode efface l'ambiguïté précisément parce qu'elle remplit la condition nécessaire pour être le plus précis .
Autrement dit, (int, long) peut être passé à (int, double), (long, long) ou (double, long) sans erreurs de compilation.
la source
C'est en effet une question très intéressante. Passons en revue la spécification du langage Java étape par étape.
Lorsque le compilateur essaie d'identifier des méthodes potentiellement applicables, la première chose qu'il fait est de rechercher les méthodes applicables par Strict Invocation .
Dans votre cas, il n'y a pas de telles méthodes, donc la prochaine étape consiste à trouver des méthodes applicables par Loose Invocation
À ce stade, toutes les méthodes correspondent, de sorte que la méthode la plus spécifique ( §15.12.2.5 ) est choisie parmi les méthodes applicables par invocation lâche.
C'est un moment clé, alors regardons cela de près.
(Nous nous intéressons uniquement au cas suivant):
Autrement dit, une méthode est plus spécifique si tous ses types de paramètres sont plus spécifiques . Et
L'expression
S <: T
signifie queS
c'est un sous-type deT
. Pour les primitives, nous avons la relation suivante:Examinons donc vos méthodes et voyons laquelle est plus spécifique que d'autres.
Dans cet exemple, le premier paramètre de la méthode 1 est évidemment plus spécifique que le premier paramètre de la méthode 2 (si vous les appelez avec des valeurs entières:)
printSum(1, 2)
. Mais le deuxième paramètre est plus spécifique pour la méthode 2 , carlong < double
. Aucune de ces méthodes n'est donc plus spécifique qu'une autre. Voilà pourquoi vous avez une ambiguïté ici.Dans l'exemple suivant:
le premier type de paramètre de la méthode 1 est plus spécifique que celui de la méthode 2, car
int < long
et le deuxième type de paramètre est le même pour les deux, c'est pourquoi la méthode 1 est choisie.la source
double
n'est pas plus précis quelong
. Et pour que la méthode soit choisie, tous les paramètres de type doivent être plus spécifiques: le type Si est plus spécifique que Ti pour l'argument ei pour tout i (1 ≤ i ≤ n, n = k)car la valeur int peut également être considérée comme double en java. signifie
double a = 3
est valide et même avec le longlong b = 3
C'est pourquoi il crée une ambiguïté. Tu appellesEst déroutant pour les trois méthodes, car toutes ces trois sont valides:
Vous pouvez mettre le L à la fin pour spécifier qu'il s'agit d'une valeur longue. par exemple:
pour le double, vous devez le convertir:
lire également le commentaire de @Erwin Bolwidt
la source