Frage

Ich habe das hier gesehen eine Antwort auf eine andere Frage, in Bezug auf Mängel der Java-Spezifikation:

Es gibt noch mehr Mängel und das ist ein heikles Thema.Überprüfen Das aus:

public class methodOverloading{
     public static void hello(Integer x){
          System.out.println("Integer");
     }

     public static void hello(long x){
          System.out.println("long");
     }

     public static void main(String[] args){
         int i = 5;
         hello(i);
     }
}

Hier würde „long“ gedruckt werden (ich habe es selbst nicht überprüft), da der Compiler die Erweiterung dem Auto-Boxing vorzieht.Seien Sie vorsichtig bei der Verwendung von Auto-Boxing oder verwenden Sie es überhaupt nicht!

Sind wir sicher, dass es sich tatsächlich um ein Beispiel für Widening statt Autoboxing handelt, oder handelt es sich um etwas ganz anderes?

Bei meinem ersten Scan würde ich der Aussage zustimmen, dass die Ausgabe „lang“ sein würde, basierend auf i als Primitiv und nicht als Objekt deklariert werden.Allerdings, wenn Sie sich geändert haben

hello(long x)

Zu

hello(Long x)

Die Ausgabe würde „Integer“ ausgeben.

Was ist hier wirklich los?Ich weiß nichts über die Compiler/Bytecode-Interpreter für Java ...

War es hilfreich?

Lösung

Im ersten Fall findet eine weitreichende Konvertierung statt.Dies kann man sehen, wenn man das Dienstprogramm „javap“ (im JDK enthalten) für die kompilierte Klasse ausführt:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   i2l
   4:   invokestatic    #6; //Method hello:(J)V
   7:   return

}

Deutlich sehen Sie I2L, die Mnemonik für die erweiternde Integer-To-Long-Bytecode-Anweisung.Siehe Referenz Hier.

Und im anderen Fall, wenn Sie das „lange x“ durch die Objektsignatur „Langes x“ ersetzen, erhalten Sie diesen Code in der Hauptmethode:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_ 5
   1:   istore_ 1
   2:   iload_ 1
   3:   invokestatic    #6; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   6:   invokestatic    #7; //Method hello:(Ljava/lang/Integer;)V
   9:   return

}

Sie sehen also, dass der Compiler die Anweisung Integer.valueOf(int) erstellt hat, um das Grundelement in den Wrapper einzuschließen.

Andere Tipps

Ja, das ist es, probieren Sie es in einem Test aus.Es wird „lang“ gedruckt.Es handelt sich um eine Erweiterung, weil Java sich dafür entscheidet, das int zu long zu erweitern, bevor es es automatisch in eine ganze Zahl umwandelt. Deshalb wird die hello(long)-Methode zum Aufrufen ausgewählt.

Bearbeiten: der ursprüngliche Beitrag, auf den verwiesen wird.

Weitere Bearbeitung:Der Grund dafür, dass die zweite Option „Integer“ ausgeben würde, liegt darin, dass es keine „Erweiterung“ in ein größeres Grundelement als Option gibt, also MUSS sie eingepackt werden, daher ist „Integer“ die einzige Option.Darüber hinaus führt Java nur eine Autobox-Operation auf den ursprünglichen Typ durch, sodass es zu einem Compilerfehler kommen würde, wenn Sie „hello(Long)“ belassen und „hello(Integer)“ entfernen.

Ein weiterer interessanter Aspekt dieses Beispiels ist die Methodenüberladung.Die Kombination aus Typerweiterung und Methodenüberladung funktioniert nur, weil der Compiler entscheiden muss, welche Methode er wählen soll.Betrachten Sie das folgende Beispiel:

public static void hello(Collection x){
   System.out.println("Collection");
}

public static void hello(List x){
   System.out.println("List");
}

public static void main(String[] args){
   Collection col = new ArrayList();
   hello(col);
}

Es verwendet nicht den Laufzeittyp „List“, sondern den Kompilierzeittyp „Collection“ und gibt daher „Collection“ aus.

Ich ermutige Sie zum Lesen Effektives Java, was mir die Augen für einige Eckfälle des JLS öffnete.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top