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


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)


1
Ви впевнені, що це не Byte b = 5;зі столицею B.
Joop Eggen

4
Я потрапляю long, longна Java8 теж FYI ... Не впевнений, чому бути чесним, чекаю також відповіді :)
sp00m

Відповіді:


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 розширення перетворення .


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результат.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.