Me topé con este fragmento:
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);
}
}
Esto dará como resultado un error de compilación:
Error: (15, 9) java: la referencia a printSum es ambigua tanto en el método printSum (int, double) en ParamTest como en el método printSum (long, long) en ParamTest match
¿Cómo es esto ambiguo? ¿No debería promoverse solo el segundo parámetro en este caso ya que el primer parámetro ya es un int? El primer parámetro no necesita ser promovido en este caso, ¿verdad?
La compilación tiene éxito si actualizo el código para agregar otro método:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Déjame expandirme solo para aclarar. El siguiente código genera ambigüedad:
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);
}
}
Entonces, este código a continuación también genera ambigüedad:
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);
}
}
Sin embargo, este no da lugar a la ambigüedad:
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
fuente
fuente
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
- no es el método lo que es ambiguo, es la llamada al método lo que es ambiguo.Respuestas:
Creo que esto tiene algo que ver con la regla específica de JLS sobre 15.12.2.5. Elegir el método más específico . Se afirma que:
El texto explica cómo Java elige el método más específico :
En el caso de su ejemplo, todos los métodos son accesibles y aplicables a la invocación de métodos, por lo tanto, Java necesita determinar cuál de ellos es más específico .
Para estos métodos, no se puede determinar que sea más específico:
El cuarto método borra la ambigüedad precisamente porque cumple la condición necesaria para ser más específico .
Es decir, (int, long) puede pasarse a (int, double), (long, long) o (double, long) sin errores de compilación.
fuente
De hecho, es una pregunta muy interesante. Veamos paso a paso la especificación del lenguaje Java.
Cuando el compilador intenta identificar métodos potencialmente aplicables, lo primero que hace es buscar métodos aplicables por invocación estricta .
En su caso, no existen tales métodos, por lo que el siguiente paso es encontrar los métodos aplicables por Invocación flexible
En este punto, todos los métodos coinciden, por lo que el método más específico ( §15.12.2.5 ) se elige entre los métodos que son aplicables por invocación flexible.
Este es un momento clave, así que veamos esto de cerca.
(Estamos interesados solo en el siguiente caso):
En pocas palabras, un método es más específico si todos sus tipos de parámetros son más específicos . Y
Expresión
S <: T
significa queS
es un subtipo deT
. Para los primitivos tenemos la siguiente relación:Así que echemos un vistazo a sus métodos y veamos cuál es más específico que otros.
En este ejemplo, el primer parámetro del método 1 es obviamente más específico que el primer parámetro del método 2 (si los llama con valores enteros:)
printSum(1, 2)
. Pero el segundo parámetro es más específico para el método 2 , porquelong < double
. Por lo tanto, ninguno de estos métodos es más específico que otro. Es por eso que tienes una ambigüedad aquí.En el siguiente ejemplo:
el primer tipo de parámetro del método 1 es más específico que el del método 2, porque
int < long
y el segundo tipo de parámetro es el mismo para ambos, por eso se elige el método 1.fuente
double
no es más específico quelong
. Y para que el método sea elegido, todos los parámetros de tipo deben ser más específicos: el tipo Si es más específico que Ti para el argumento ei para todo i (1 ≤ i ≤ n, n = k)porque el valor int también se puede considerar como doble en java. significa
double a = 3
es válido y lo mismo con el largolong b = 3
Entonces, por eso está creando una ambigüedad. LlamaEs confuso para los tres métodos, porque todos estos tres son válidos:
Puede poner la L al final, para especificar que es un valor largo. por ejemplo:
para el doble necesitas convertirlo:
También lea el comentario de @Erwin Bolwidt
fuente