Warum erstreckt sich Java Autoboxing nicht auf Methodenaufrufe von Methoden der Autobox-Typen?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

Frage

Ich möchte ein Grundelement in eine Zeichenfolge konvertieren und habe Folgendes versucht:

myInt.toString();

Dies schlägt mit dem Fehler fehl:

int cannot be dereferenced

Nun verstehe ich, dass Primitive keine Referenztypen (dh kein Objekt) sind und daher keine Methoden haben können.Allerdings führte Java 5 Autoboxing und Unboxing ein (a la C#...)was mir in C# nie gefallen hat, aber das ist nebensächlich).Beim Autoboxing würde ich also erwarten, dass das Obige myInt in eine Ganzzahl konvertiert und dann toString() dafür aufruft.

Darüber hinaus glaube ich, dass C# einen solchen Aufruf zulässt, sofern ich mich nicht falsch erinnere.Ist das nur ein bedauerlicher Mangel der Autoboxing/Unboxing-Spezifikation von Java, oder gibt es dafür einen guten Grund?

War es hilfreich?

Lösung

Das Java-Autoboxing/Unboxing geht nicht so weit, dass Sie ein Grundelement dereferenzieren können, daher verhindert Ihr Compiler dies.Ihr Compiler weiß es immer noch myInt als Primitiv.Es gibt einen Artikel zu diesem Thema unter jcp.org.

Autoboxing ist vor allem bei Zuweisungen oder Parameterübergaben nützlich – es ermöglicht Ihnen, ein Grundelement als Objekt zu übergeben (oder umgekehrt) oder einem Objekt ein Grundelement zuzuweisen (oder umgekehrt).

Daher müsste man es leider so machen:(Ein großes Lob an Patrick, ich bin auf deinen Weg umgestiegen)

Integer.toString(myInt);

Andere Tipps

Das Gleiche gilt für das, was Justin gesagt hat, aber Sie sollten stattdessen Folgendes tun:

Integer.toString(myInt);

Es spart ein oder zwei Zuordnungen und ist besser lesbar.

Eine andere Möglichkeit, dies zu tun, besteht darin, Folgendes zu verwenden:

String.valueOf(myInt);

Diese Methode ist für jeden primitiven Typ und überladen Object.Auf diese Weise müssen Sie nicht einmal darüber nachdenken, welchen Typ Sie verwenden.Implementierungen der Methode rufen für Sie die entsprechende Methode des angegebenen Typs auf, z. B. Integer.toString(myInt).

Sehen http://java.sun.com/javase/6/docs/api/java/lang/String.html.

Scheint ein Mangel der Spezifikation für mich

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 (habe es selbst nicht überprüft), da der Compiler die Erweiterung dem Autoboxing vorzieht.Seien Sie vorsichtig bei der Verwendung von Autoboxing oder verwenden Sie es überhaupt nicht!

Die Ihrem Beispiel am nächsten kommende gültige Syntax lautet

((Integer) myInt).toString();

Wenn der Compiler fertig ist, ist das äquivalent zu

Integer.valueOf(myInt).toString();

Allerdings ist die Leistung nicht so gut wie bei der herkömmlichen Verwendung. String.valueOf(myInt), da außer in Sonderfällen eine neue Integer-Instanz erstellt und dann sofort verworfen wird, was zu noch mehr unnötigem Müll führt.(Ein kleiner Bereich von Ganzzahlen wird zwischengespeichert und über einen Array-Zugriff aufgerufen.) Vielleicht wollten Sprachdesigner aus Leistungsgründen von dieser Verwendung abraten.

Bearbeiten:Ich würde es begrüßen, wenn die Downvoter einen Kommentar dazu abgeben würden, warum dies nicht hilfreich ist.

In C# sind Ganzzahlen weder Referenztypen noch müssen sie dafür eingerahmt werden ToString() heißen.Sie Sind werden jedoch als Objekte im Framework betrachtet (als ValueType, sodass sie eine Wertesemantik haben).In der CLR werden Methoden für Grundelemente aufgerufen, indem sie „indirekt“ auf den Stapel (ldind) geladen werden.

Wie jeder betont hat, können Sie mit Autoboxing einige Codes vereinfachen, aber Sie können nicht so tun, als wären Grundelemente komplexe Typen.

Auch interessant: „Autoboxing ist ein Hack auf Compiler-Ebene“ in Java.Autoboxing ist im Grunde ein seltsamer Trick, der Java hinzugefügt wurde.Kasse dieser Beitrag Weitere Informationen darüber, wie seltsam es ist.

Es wäre hilfreich, wenn Java bestimmte statische Methoden definieren würde, um mit primitiven Typen zu arbeiten, und dafür etwas syntaktischen Zucker in den Compiler einbauen würde

5.asInteger

wäre gleichbedeutend mit

some.magic.stuff.Integer.asInteger(5);

Ich glaube nicht, dass eine solche Funktion zu Inkompatibilität mit Code führen würde, der nach den aktuellen Regeln kompiliert wird, und sie würde in vielen Fällen dazu beitragen, syntaktisches Durcheinander zu reduzieren.Wenn Java dereferenzierte Primitive automatisch in Boxen umwandeln würde, könnte man annehmen, dass es die Dereferenzierungssyntax statischen Methodenaufrufen zuordnet (was praktisch in .NET der Fall ist) und dass in dieser Form geschriebene Vorgänge daher nicht teurer wären als es wäre die entsprechenden statischen Methodenaufrufe.Hinzufügen einer neuen Sprachfunktion, die Menschen dazu ermutigen würde, schlechten Code zu schreiben (z. B.Das automatische Boxen dereferenzierter Grundelemente scheint keine gute Idee zu sein, das Zulassen von Methoden im Dereferenzierungsstil könnte jedoch eine gute Idee sein.

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