Przekazywanie argumentów bajtów do przeciążonej metody

12

Wziąłem ten fragment kodu z jakiegoś quizu, używając IDE wykonałem go i otrzymałem wynik długi, długi, ale poprawna odpowiedź to Bajt, Bajt , dlaczego mam inny wynik? Pytanie dotyczy 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);
    }
}

EDYTOWANE:

Kod został pobrany tutaj: Przegląd certyfikacji Oracle i przykładowe pytania (Strona: 13, Pytanie: 5)

kbo
źródło
1
Czy na pewno nie jest Byte b = 5;to duże B.
Joop Eggen
4
long, longDostaję też Java8 zbyt FYI ... Nie jestem pewien, dlaczego mam być szczery, też czekam na odpowiedź :)
sp00m
Możliwy duplikat metody Java z przeciążeniem boksem / poszerzeniem
Pavel Smirnov

Odpowiedzi:

6

Jeśli więc przejrzysz specyfikację języka Java w celu ustalenia podpisu metody w czasie kompilacji, będzie jasne:

  1. Pierwsza faza (§15.12.2.2) wykonuje rozwiązywanie przeciążenia bez zezwolenia na konwersję boksu lub rozpakowanie lub użycie metody wywołania zmiennej arity. Jeżeli podczas tej fazy nie zostanie znaleziona żadna odpowiednia metoda, przetwarzanie przechodzi do drugiej fazy.

  2. Druga faza (§15.12.2.3) wykonuje rozwiązywanie przeciążenia, umożliwiając boksowanie i rozpakowywanie, ale nadal wyklucza stosowanie wywoływania metody zmiennej arity. Jeżeli podczas tej fazy nie zostanie znaleziona żadna odpowiednia metoda, przetwarzanie przechodzi do trzeciej fazy.

  3. Trzecia faza (§15.12.2.4) pozwala na połączenie przeciążenia ze zmiennymi metodami arsenału, boksowania i rozpakowywania.

Tak więc z powyższych kroków jasne jest, że w twoim przypadku w pierwszej fazie kompilator Java znajdzie pasującą metodę, która to robi doCalc(long a,long b). Twoja metoda doCalc(Byte s1, Byte s2)wymaga automatycznego połączenia podczas połączenia, aby uzyskać mniej preferencji.

Amit Bera
źródło
1
Jeśli chodzi o to, dlaczego longakceptuje byte, wydaje się podążać za rozszerzającą się prymitywną konwersją : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Więc w zasadzie, +widening -boxing -varargspo czym +widening +boxing -varargsnastępnie +widening +boxing +varargs.
sp00m
@kbo Dlaczego uważasz, że poprawna odpowiedź to Byte, Byte?
Amit Bera,
3
@kbo Wydaje mi się, że poprawna odpowiedź jest niepoprawna :) Jeśli to możliwe, warto wskazać autorom to pytanie.
sp00m
3
@ sp00m Znalazłem to pytanie w próbkach Oracle, spójrz na edytowaną część
kbo
@kbo Wow ... Nie mam pojęcia, jak postępować!
sp00m
2

Przeczytaj rozdział JLS na temat konwersji .

W twoim przypadku JVM decyduje się na rozszerzenie konwersji, byte -> long ponieważ konwersja jest bezpieczniejsza, ponieważ gwarantuje, że nie spowoduje RuntimeException.

Konwersja z bytena Bytezwany również boksem może spowodować OutOfMemoryError, ponieważ JVM musi przydzielić nowe obiekty do sterty:

Konwersja boksu może spowodować błąd OutOfMemoryError, jeśli konieczne jest przydzielenie nowego wystąpienia jednej z klas opakowań (Boolean, Byte, Character, Short, Integer, Long, Float lub Double) i dostępna jest niewystarczająca ilość pamięci.

Z tego powodu preferowana jest bezpieczniejsza byte -> long konwersja poszerzająca .

diginoise
źródło
2
Uwaga: boksowanie od bytedo Bytenigdy nie powoduje OutOfMemoryException, ponieważ wszystkie wartości Byte(-128 - 127) są buforowane wewnętrznie. Ale może nie być tak samo z innymi typami, więc zgodnie z ogólną zasadą priorytetem jest poszerzenie konwersji.
Pavel Smirnov
1

Aby znaleźć prawidłowe przeciążenie, kolejność jest następująca:

  1. według liczby parametrów
  2. boks / unboxing
  3. parametry variadic

Więc

  • W przypadku b, gdy Bytewynik będzie Byte, Byte.
  • Gdyby zdano, new byte[] { b, b }wynik byłby byte, byte.
  • Jeśli miną dwa bajty b, możliwe jest rozszerzenie z bajtu na int na długi i wynikiem jest long, long.
  • Po usunięciu dużego, długiego przeciążenia Byte, Bytewyniki.
Joop Eggen
źródło