Eu tropecei neste trecho:
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);
}
}
Isso resultará em um erro de compilação:
Erro: (15, 9) java: a referência a printSum é ambígua, tanto o método printSum (int, double) no ParamTest quanto o método printSum (long, long) na correspondência do ParamTest
Como isso é ambíguo? Nesse caso, não deve ser promovido apenas o segundo parâmetro, pois o primeiro parâmetro já é um int? O primeiro parâmetro não precisa ser promovido neste caso, certo?
A compilação terá êxito se eu atualizar o código para adicionar outro método:
public static void printSum(int a, long b) {
System.out.println(String.format("%s, %s ", a, b));
}
Deixe-me expandir apenas para esclarecer. O código abaixo resulta em ambiguidade:
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);
}
}
Então este código abaixo também resulta em ambiguidade:
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);
}
}
No entanto, este não resulta em ambiguidade:
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
fonte
fonte
Error:(15, 9) java: reference to printSum is ambiguous both method printSum(int,double) in ParamTest and method printSum(long,long) in ParamTest match
- não é o método ambíguo, é a chamada para o método ambíguo.Respostas:
Eu acho que isso tem algo a ver com a regra específica do JLS sobre 15.12.2.5. Escolhendo o método mais específico . Diz que:
Como o Java escolhe o método mais específico é explicado mais detalhadamente pelo texto:
No caso do seu exemplo, todos os métodos são acessíveis e aplicáveis à invocação de métodos; portanto, o Java precisa determinar qual deles é mais específico .
Para esses métodos, nenhum pode ser determinado como mais específico:
O quarto método elimina a ambiguidade precisamente porque preenche a condição necessária para ser mais específico .
Ou seja, (int, long) pode ser passado para (int, double), (long, long) ou (double, long) sem erros de compilação.
fonte
É realmente uma pergunta muito interessante. Vamos examinar a Especificação de Linguagem Java passo a passo.
Quando o compilador está tentando identificar métodos potencialmente aplicáveis, a primeira coisa que faz é procurar métodos aplicáveis pela Invocação Restrita .
No seu caso, não existem métodos desse tipo, portanto, a próxima etapa é encontrar métodos aplicáveis pela Loose Invocation
Nesse ponto, todos os métodos coincidem; portanto, o método mais específico ( §15.12.2.5 ) é escolhido entre os métodos aplicáveis por invocação solta.
Este é um momento chave, então vamos ver isso de perto.
(Estamos interessados apenas no seguinte caso):
Simplificando, um método é mais específico se todos os seus tipos de parâmetros forem mais específicos . E
Expressão
S <: T
significa queS
é um subtipo deT
. Para primitivos, temos o seguinte relacionamento:Então, vejamos seus métodos e vejamos qual é mais específico que outros.
Neste exemplo, o primeiro parâmetro do método 1 é obviamente mais específico que o primeiro parâmetro do método 2 (se você os chamar com valores inteiros:)
printSum(1, 2)
. Mas o segundo parâmetro é mais específico para o método 2 , porquelong < double
. Portanto, nenhum desses métodos é mais específico que outro. É por isso que você tem uma ambiguidade aqui.No exemplo a seguir:
o primeiro tipo de parâmetro do método 1 é mais específico que o método 2, porque
int < long
e o segundo tipo de parâmetro é o mesmo para os dois, é por isso que o método 1 é escolhido.fonte
double
não é mais específico do quelong
. E para o método a ser escolhido, todos os parâmetros de tipo devem ser mais específicos: o tipo Si é mais específico do que Ti para o argumento ei para todos os i (1 ≤ i ≤ n, n = k)porque o valor int também pode ser considerado como duplo em java. meios
double a = 3
é válido e o mesmo com o longolong b = 3
É por isso que está criando uma ambiguidade. Você chamaÉ confuso para todos os três métodos, porque todos esses três são válidos:
Você pode colocar L no final, para especificar que é um valor longo. por exemplo:
para o dobro, você precisa convertê-lo:
leia também o comentário do @Erwin Bolwidt
fonte