Passando argumentos de bytes para o método sobrecarregado

12

Peguei esse trecho de código de algum teste, usando o IDE, executei-o e obtive um resultado obtive longo, longo, mas a resposta correta é Byte, Byte , por que obtive resultados diferentes? A questão está relacionada ao JDK 11

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

EDITADO:

O código foi obtido aqui: Visão geral da certificação Oracle e perguntas de exemplo (Página: 13, Pergunta: 5)

kbo
fonte
11
Tem certeza de que não é Byte b = 5;com um capital B.
Joop Eggen
4
Eu fico long, longem Java8 também FYI ... Não sei por que, para ser honesto, à espera de uma resposta também :)
sp00m
Possível duplicado de Java sobrecarga de método com Boxe / Alargamento
Pavel Smirnov

Respostas:

6

Portanto, se você examinar a especificação da linguagem Java para determinar a assinatura do método no momento da compilação, ficará claro:

  1. A primeira fase (§15.12.2.2) executa a resolução de sobrecarga sem permitir a conversão de boxe ou unboxing ou o uso de invocação de método de variável variável. Se nenhum método aplicável for encontrado durante esta fase, o processamento continuará na segunda fase.

  2. A segunda fase (§15.12.2.3) executa a resolução de sobrecarga enquanto permite boxe e unboxing, mas ainda impede o uso de invocação de método de variável variável. Se nenhum método aplicável for encontrado durante esta fase, o processamento continuará na terceira fase.

  3. A terceira fase (§15.12.2.4) permite que a sobrecarga seja combinada com métodos de aridade variável, boxe e desembalagem.

Portanto, a partir das etapas acima, é claro que, no seu caso, na primeira fase, o compilador Java encontrará um método correspondente doCalc(long a,long b). Seu método doCalc(Byte s1, Byte s2)precisa de uma caixa automática durante a chamada para obter menos preferência.

Amit Bera
fonte
11
Em relação ao porquê longaceita byte, parece seguir uma conversão primitiva cada vez maior : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Então, basicamente,+widening -boxing -varargs em seguida, +widening +boxing -varargsem seguida +widening +boxing +varargs.
Sp00m 07/10/19
@kbo Por que você acha que a resposta correta é Byte, Byte?
Amit Bera
3
@ kbo Acho que a resposta correta está incorreta :) Pode valer a pena apontar os autores para esta pergunta, se puder.
Sp00m
3
@ sp00m Encontrei essa pergunta nos exemplos da Oracle, dê uma olhada na parte editada
kbo
@kbo Wow ... Não faço ideia de como proceder então!
Sp00m
2

Leia o capítulo JLS sobre conversões .

O que está acontecendo no seu caso é que, durante o tempo de execução, a JVM opta por executar uma conversão ampliada, byte -> long pois essa conversão é mais segura porque é garantido que não causa RuntimeException.

A conversão de bytepara Bytetambém chamado de boxe pode resultar em OutOfMemoryError, pois a JVM precisa alocar novos objetos no heap:

Uma conversão de caixa pode resultar em OutOfMemoryError se uma nova instância de uma das classes de wrapper (Booleana, Byte, Caractere, Curta, Inteira, Longa, Flutuante ou Dupla) precisar ser alocada e houver armazenamento insuficiente disponível.

Por esse byte -> long motivo, é preferível a conversão de alargamento mais segura .

diginoise
fonte
2
Apenas para observar, o boxe de bytepara Bytenunca causa OutOfMemoryException, pois todos os valores de Byte(-128 - 127) são armazenados em cache internamente. Mas pode não ser o mesmo com outros tipos, portanto, como regra geral, o aumento da conversão ganha prioridade.
Pavel Smirnov
1

Para encontrar a sobrecarga correta, o pedido é:

  1. por número de parâmetros
  2. boxe / unboxing
  3. parâmetros variadicos

assim

  • Se bonde um Byteresultado seria Byte, Byte.
  • Se passado teria sido new byte[] { b, b }o resultado seria byte, byte.
  • Se for passado dois bytes by, é possível uma ampliação de byte para int para long e o resultado é long, long.
  • Quando a sobrecarga longa e longa é removida, Byte, Byteresulta.
Joop Eggen
fonte