Передача байтовых аргументов перегруженному методу

12

Я взял этот фрагмент кода из какой-то викторины, используя IDE, я выполнил его и получил длинный, длинный ответ , но правильный ответ - Байт, Байт , почему я получил другой результат? Вопрос связан с 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);
    }
}

Отредактированный:

Код был взят здесь: Обзор сертификации Oracle и примеры вопросов (Страница: 13, Вопрос: 5)

KBO
источник
1
Вы уверены, что это не Byte b = 5;с большой буквы?
Joop Eggen
4
Я получаю long, longна Java8 тоже FYI ... Не уверен, почему, если честно, жду ответа тоже :)
sp00m
Возможный дубликат перегрузки метода Java с помощью бокса / расширения
Павел Смирнов,

Ответы:

6

Так что , если вы идете через язык Java спецификацию для определения сигнатуры методы во время компиляции станет ясно:

  1. Первая фаза (§15.12.2.2) выполняет разрешение перегрузки, не разрешая преобразование в коробку или распаковку или использование вызова метода переменной арности. Если на этом этапе не найдено подходящего метода, обработка продолжается до второго этапа.

  2. Вторая фаза (§15.12.2.3) выполняет разрешение перегрузки, в то же время разрешая упаковывать и распаковывать, но все же исключает использование вызова метода переменной арности. Если на этом этапе не найдено подходящего метода, обработка продолжается до третьего этапа.

  3. Третья фаза (§15.12.2.4) позволяет сочетать перегрузку с методами переменной арности, упаковкой и распаковкой.

Итак, из приведенных выше шагов ясно, что в вашем случае на первом этапе компилятор Java найдет подходящий метод, который это делает doCalc(long a,long b). Ваш метод doCalc(Byte s1, Byte s2)нуждается в автобоксе во время вызова, поэтому он будет иметь меньше предпочтений.

Амит Бера
источник
1
Относительно того, почему longпринимает byte, кажется, следует расширение примитивного преобразования : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Таким образом , в основном, +widening -boxing -varargsто +widening +boxing -varargsпотом +widening +boxing +varargs.
sp00m
@kbo Почему вы думаете, что правильный ответ Byte, Byte?
Амит Бера
3
@kbo Полагаю, правильный ответ неправильный :) Возможно, стоит указать авторам этого вопроса, если можете.
sp00m
3
@ sp00m Я нашел этот вопрос в примерах Oracle, пожалуйста, взгляните на отредактированную часть
kbo
@kbo Ух ты ... Не знаю, как действовать дальше!
sp00m
2

Пожалуйста, прочитайте главу JLS о конверсиях .

В вашем случае происходит то, что во время выполнения JVM решает выполнить расширенное преобразование, так byte -> long как это преобразование безопаснее, поскольку гарантируется, что оно не вызывает RuntimeException.

Преобразование из byteв Byteтакже вызываемый бокс может привести к OutOfMemoryError, поскольку JVM должна разместить новые объекты в куче:

Конверсионное преобразование может привести к OutOfMemoryError, если требуется выделить новый экземпляр одного из классов-оболочек (Boolean, Byte, Character, Short, Integer, Long, Float или Double) и недостаточно места для хранения.

Из-за этого более безопасное byte -> long расширение конверсии является предпочтительным.

diginoise
источник
2
Просто к сведению, бокс от byteдо Byteникогда не вызывает OutOfMemoryException, так как все значения Byte(-128 - 127) внутренне кэшируются. Но это может не совпадать с другими типами, поэтому, как правило, расширение конверсии получает приоритет.
Павел Смирнов
1

Для нахождения правильной перегрузки, порядок:

  1. по количеству параметров
  2. бокс / распаковка
  3. переменные параметры

Так

  • Если bгде Byteрезультат будет Byte, Byte.
  • Если бы прошло, был new byte[] { b, b }бы результат byte, byte.
  • Если передано два байта b, возможно расширение от байта к int до long, и результат будет long, long.
  • Когда длинная, длинная перегрузка устранена, Byte, Byteрезультаты.
Joop Eggen
источник