Übergabe von Byteargumenten an eine überladene Methode

12

Ich habe dieses Code-Snippet aus einem Quiz genommen, es mit IDE ausgeführt und ein langes, langes Ergebnis erhalten , aber die richtige Antwort lautet Byte, Byte , warum habe ich ein anderes Ergebnis erhalten? Die Frage bezieht sich auf 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);
    }
}

EDITIERT:

Der Code wurde hier aufgenommen: Oracle-Zertifizierungsübersicht und Beispielfragen (Seite: 13, Frage: 5)

kbo
quelle
1
Sind Sie sicher, dass es nicht Byte b = 5;mit einer Hauptstadt B ist?
Joop Eggen
4
Ich komme auch long, longauf Java8 FYI ... Ich bin mir nicht sicher, warum ich ehrlich sein soll und warte auch auf eine Antwort :)
sp00m
Mögliches Duplikat der Java-Methodenüberladung mit Boxen / Erweitern
Pavel Smirnov

Antworten:

6

Also, wenn Sie die Java - Sprache durch Spezifikation Methodensignatur bei der Kompilierung zur Bestimmung klar sein wird:

  1. In der ersten Phase (§15.12.2.2) wird eine Überlastungsauflösung durchgeführt, ohne dass eine Boxing- oder Unboxing-Konvertierung oder die Verwendung eines Methodenaufrufs mit variabler Arität zulässig ist. Wenn während dieser Phase keine anwendbare Methode gefunden wird, wird die Verarbeitung zur zweiten Phase fortgesetzt.

  2. Die zweite Phase (§15.12.2.3) führt eine Überlastungsauflösung durch, während das Ein- und Auspacken zugelassen wird, schließt jedoch die Verwendung des Aufrufs einer Methode mit variabler Arität aus. Wenn während dieser Phase keine anwendbare Methode gefunden wird, wird die Verarbeitung zur dritten Phase fortgesetzt.

  3. Die dritte Phase (§15.12.2.4) ermöglicht die Kombination von Überladung mit Methoden mit variabler Arität, Boxen und Entpacken.

Aus den obigen Schritten geht hervor, dass der Java-Compiler in Ihrem Fall in der ersten Phase eine passende Methode findet, die dies tut doCalc(long a,long b). Ihre Methode doCalc(Byte s1, Byte s2)benötigt während des Aufrufs eine Autobox, damit sie weniger bevorzugt wird.

Amit Bera
quelle
1
In Bezug auf das longAkzeptieren bytescheint eine sich erweiternde primitive Konvertierung zu folgen : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Also im Grunde, +widening -boxing -varargsdann +widening +boxing -varargsdann +widening +boxing +varargs.
sp00m
@kbo Warum denkst du, ist die richtige Antwort Byte, Byte?
Amit Bera
3
@kbo Ich denke, die richtige Antwort ist falsch :) Könnte es wert sein, die Autoren auf diese Frage hinzuweisen, wenn Sie können.
sp00m
3
@ sp00m Ich habe diese Frage in den Beispielen von Oracle gefunden. Bitte werfen Sie einen Blick auf den bearbeiteten Teil
kbo
@kbo Wow ... Keine Ahnung wie ich dann vorgehen soll!
sp00m
2

Bitte lesen Sie das JLS-Kapitel über Conversions .

In Ihrem Fall führt JVM zur Laufzeit eine erweiterte Konvertierung durch, byte -> long da diese Konvertierung sicherer ist, da garantiert ist, dass dies keine Ursache istRuntimeException .

Das Konvertieren von bytein Byteauch als Boxing bezeichnet kann zu OutOfMemoryError führen, da die JVM dem Heap neue Objekte zuweisen muss:

Eine Boxkonvertierung kann zu einem OutOfMemoryError führen, wenn eine neue Instanz einer der Wrapper-Klassen (Boolean, Byte, Character, Short, Integer, Long, Float oder Double) zugewiesen werden muss und nicht genügend Speicher verfügbar ist.

Aus diesem Grund wird die sicherere byte -> long Verbreiterung bevorzugt.

diginoise
quelle
2
Nur zu beachten, Boxen von bytebis Bytenie verursacht OutOfMemoryException, da alle Werte von Byte(-128 - 127) intern zwischengespeichert werden. Bei anderen Typen ist dies jedoch möglicherweise nicht der Fall. Daher gilt als Faustregel, dass die Erweiterung der Konvertierung Vorrang hat.
Pavel Smirnov
1

Um die richtige Überlastung zu finden, lautet die Reihenfolge:

  1. nach Anzahl der Parameter
  2. Boxen / Unboxen
  3. verschiedene Parameter

Damit

  • Wenn bwo ein Bytedas Ergebnis wäre Byte, Byte.
  • Wenn bestanden worden wäre, wäre new byte[] { b, b }das Ergebnis byte, byte.
  • Wenn zwei Bytes b übergeben werden, ist eine Erweiterung von Byte zu int zu long möglich und das Ergebnis ist long, long.
  • Wenn die lange, lange Überlastung beseitigt wird, Byte, Byteergibt sich.
Joop Eggen
quelle