Autoboxing ist die automatische Konvertierung, die der Java-Compiler zwischen den primitiven Typen und den entsprechenden Objekt-Wrapper-Klassen vornimmt. Beispiel: Konvertieren eines int in eine Ganzzahl, eines Double in ein Double usw. Wenn die Konvertierung in die andere Richtung erfolgt, wird dies als Unboxing bezeichnet.
Warum brauchen wir es und warum verwenden wir Autoboxing und Unboxing in Java?
java
autoboxing
Theodoros Chatzigiannakis
quelle
quelle
Integer
hatparseInt
Methode.int
hat nicht. :)List<Integer>
, aber Sie können nicht habenList<int>
.Antworten:
Ein gewisser Kontext ist erforderlich, um den Hauptgrund dafür vollständig zu verstehen.
Primitive versus Klassen
Primitive Variablen in Java enthalten Werte (eine Ganzzahl, eine Gleitkomma-Binärzahl mit doppelter Genauigkeit usw.). Da diese Werte unterschiedliche Längen haben können , können die Variablen, die sie enthalten, auch unterschiedliche Längen haben (siehe
float
versusdouble
).Andererseits enthalten Klassenvariablen Verweise auf Instanzen. Referenzen werden normalerweise in vielen Sprachen als Zeiger (oder ähnlich wie Zeiger) implementiert. Diese Dinge haben in der Regel die gleiche Größe, unabhängig von der Größe der Instanzen sie beziehen sich auf (
Object
,String
,Integer
, usw.).Diese Eigenschaft von Klassenvariablen macht die darin enthaltenen Referenzen (bis zu einem gewissen Grad) austauschbar . Dies ermöglicht es uns, das zu tun, was wir Substitution nennen : im Großen und Ganzen eine Instanz eines bestimmten Typs als Instanz eines anderen verwandten Typs zu verwenden ( z. B. a
String
alsObject
.Primitive Variablen sind weder untereinander noch mit auf die gleiche Weise austauschbar
Object
. Der offensichtlichste Grund dafür (aber nicht der einzige Grund) ist ihr Größenunterschied. Dies macht primitive Typen in dieser Hinsicht unpraktisch, aber wir brauchen sie immer noch in der Sprache (aus Gründen, die hauptsächlich auf die Leistung hinauslaufen).Generika und Typ Löschung
Generische Typen sind Typen mit einem oder mehreren Typparametern (die genaue Anzahl wird als generische Arität bezeichnet ). Beispielsweise verfügt die generische Typdefinition
List<T>
über einen TypparameterT
, derObject
(Erzeugen eines konkreten TypsList<Object>
),String
(List<String>
),Integer
(List<Integer>
) usw. sein kann.Generische Typen sind viel komplizierter als nicht generische. Als sie (nach ihrer ersten Veröffentlichung) in Java eingeführt wurden, beschlossen die Entwickler von Java, generische Typen auf die am wenigsten invasive Weise zu implementieren , um radikale Änderungen an der JVM zu vermeiden und möglicherweise die Kompatibilität mit älteren Binärdateien zu beeinträchtigen: alle konkreten Typen von
List<T>
sind in der Tat kompiliert zu (dem binären Äquivalent von)List<Object>
(für andere Typen kann die Grenze etwas anderes sein alsObject
, aber Sie bekommen den Punkt). Generische Aritäts- und Typparameterinformationen gehen bei diesem Prozess verloren , weshalb wir sie als Typlöschung bezeichnen .Die beiden zusammenfügen
Das Problem ist jetzt die Kombination der oben genannten Realitäten: wenn
List<T>
wirdList<Object>
in allen Fällen, dannT
muss immer ein Typ sein, der direkt zugeordnet werden kannObject
. Alles andere kann nicht erlaubt werden. Da, wie schon gesagt,int
,float
unddouble
mit nicht austauschbar sindObject
, kann es keine seinList<int>
,List<float>
oderList<double>
(es sei denn , eine wesentlich komplizierter Implementierung von Generika in der JVM existierte).Aber Java jetzt Angebote mögen
Integer
,Float
undDouble
die diese Grundelemente in Klasseninstanzen wickeln, so dass sie effektiv substituierbar wieObject
, so ermöglicht generische Typen , um indirekt die Arbeit mit der Primitiven als auch (weil Sie können habenList<Integer>
,List<Float>
,List<Double>
und so weiter).Das Erstellen eines
Integer
aus einemint
, einesFloat
aus einemfloat
und so weiter wird als Boxen bezeichnet . Das Gegenteil heißt Unboxing . Da esObject
unpraktisch ist, Primitive jedes Mal zu boxen, wenn Sie sie verwenden möchten , gibt es Fälle, in denen die Sprache dies automatisch tut - das wird Autoboxing genannt .quelle
Object
Instanzen verwenden können. Generika über Typlöschung sind eine Anwendung davon.Auto Boxing wird verwendet , um primitive Datentypen in ihre Wrapper-Klassenobjekte zu konvertieren. Die Wrapper-Klasse bietet einen breiten Funktionsumfang für die primitiven Typen. Das häufigste Beispiel ist:
int a = 56; Integer i = a; // Auto Boxing
Es wird benötigt, weil Programmierer einfach Code direkt schreiben können und JVM sich um das Boxen und Unboxen kümmert.
Auto Boxing ist auch nützlich, wenn wir mit java.util.Collection-Typen arbeiten. Wenn wir eine Sammlung primitiver Typen erstellen möchten, können wir keine Sammlung eines primitiven Typs direkt erstellen, sondern nur eine Sammlung von Objekten. Zum Beispiel :
ArrayList<int> al = new ArrayList<int>(); // not supported ArrayList<Integer> al = new ArrayList<Integer>(); // supported al.add(45); //auto Boxing
Wrapper-Klassen
Jedem der 8 primitiven Typen von Java (Byte, Short, Int, Float, Char, Double, Boolean, Long) ist eine separate Wrapper-Klasse zugeordnet. Diese Wrapper-Klassen verfügen über vordefinierte Methoden zum Ausführen nützlicher Operationen für primitive Datentypen.
Verwendung von Wrapper-Klassen
String s = "45"; int a = Integer.parseInt(s); // sets the value of a to 45.
Es gibt viele nützliche Funktionen, die Wrapper-Klassen bieten. Schauen Sie sich hier die Java-Dokumente an
Unboxing ist das Gegenteil von Auto Boxing, bei dem das Wrapper-Klassenobjekt wieder in seinen primitiven Typ konvertiert wird. Dies wird automatisch von JVM durchgeführt, damit wir die Wrapper-Klassen für bestimmte Operationen verwenden und sie dann wieder in primitive Typen konvertieren können, da primitive Ergebnisse zu einer schnelleren Verarbeitung führen. Zum Beispiel :
Integer s = 45; int a = s; auto UnBoxing;
Bei Sammlungen, die mit Objekten arbeiten, wird nur das automatische Entpacken verwendet. Hier ist wie :
ArrayList<Integer> al = new ArrayList<Integer>(); al.add(45); int a = al.get(0); // returns the object of Integer . Automatically Unboxed .
quelle
Die primitiven (Nicht-Objekt-) Typen haben dort eine Rechtfertigung für die Effizienz.
Die primitiven Typen
int, boolean, double
sind unmittelbare Daten, währendObject
s Referenzen sind. Daher Felder (oder Variablen)int i; double x; Object s;
würde lokalen Speicher 4 + 8 + 8 benötigen? wobei für das Objekt nur die Referenz (Adresse) zum Speicher gespeichert wird.
Unter Verwendung der Object-Wrapper
Integer, Double
und anderer würde eine Indirektion eingeführt, die auf eine Integer / Double-Instanz im Heap-Speicher verweist.Warum wird Boxen benötigt?
Das ist eine Frage des relativen Umfangs. In einem zukünftigen Java ist geplant
ArrayList<int>
, primitive Typen zu heben.Antwort: Derzeit funktioniert eine ArrayList nur für Object, reserviert Platz für eine Objektreferenz und verwaltet ebenfalls die Garbage Collection. Daher sind generische Typen Objektkinder. Wenn man also eine ArrayList mit Gleitkommawerten haben wollte, musste man ein Double in ein Double-Objekt einschließen.
Hier unterscheidet sich Java vom traditionellen C ++ mit seinen Vorlagen: C ++ - Klassen
vector<string>, vector<int>
würden zwei Kompilierungsprodukte erstellen. Beim Java-Design wurde eine ArrayList.class verwendet, und nicht für jeden Parametertyp wurde ein neues kompiliertes Produkt benötigt.Ohne Boxing to Object müsste man also Klassen für jedes Auftreten eines Parametertyps kompilieren. In concreto: Jede Sammlung oder Containerklasse würde eine Version für Object, int, double, boolean benötigen. Die Version für Object würde alle untergeordneten Klassen behandeln.
Tatsächlich bestand in Java SE bereits die Notwendigkeit einer solchen Diversifizierung für IntBuffer, CharBuffer, DoubleBuffer, ..., die mit int, char, double arbeiten. Es wurde auf hackige Weise gelöst, indem diese Quellen aus einer gemeinsamen Quelle generiert wurden .
quelle
Ab JDK 5 hat Java zwei wichtige Funktionen hinzugefügt: Autoboxing und Autounboxing. AutoBoxing ist der Prozess, für den ein primitiver Typ automatisch in den entsprechenden Wrapper gekapselt wird, wenn ein solches Objekt benötigt wird. Sie müssen kein Objekt explizit erstellen. Auto-Unboxing ist der Prozess, bei dem der Wert eines gekapselten Objekts automatisch aus einem Typ-Wrapper extrahiert wird, wenn sein Wert benötigt wird. Sie müssen keine Methode wie intValue () oder doubleValue () aufrufen .
Das Hinzufügen von Autoboxing und Auto-Unboxing vereinfacht das Schreiben von Algorithmen erheblich und eliminiert das manuelle Ein- und Auspacken von Werten. Es ist auch hilfreich, Fehler zu vermeiden . Dies ist auch sehr wichtig für Generika , die nur Objekte bearbeiten. Schließlich erleichtert Autoboxing die Arbeit mit dem Collections Framework .
quelle
Warum haben wir (Un) Boxen?
um das Schreiben von Code, in dem wir Grundelemente und ihre objektorientierten (OO) Alternativen mischen, komfortabler / weniger ausführlich zu gestalten.
Warum haben wir Primitive und ihre OO-Alternativen?
Primitive Typen sind keine Klassen (im Gegensatz zu C #), daher sind sie keine Unterklassen von
Object
und können nicht überschrieben werden.Wir haben Grundelemente wie
int
aus Leistungsgründen undObject
Alternativen wieInteger
für die Vorteile der OO-Programmierung und als kleinen Punkt, um einen guten Speicherort für Dienstprogrammkonstanten und -methoden (Integer.MAX_VALUE undInteger.toString(int)
) zu haben.Die OO-Vorteile sind mit Generics (
List<Integer>
) am einfachsten sichtbar , sind jedoch nicht darauf beschränkt, zum Beispiel:Number getMeSome(boolean wantInt) { if (wantInt) { return Integer.MAX_VALUE; } else { return Long.MAX_VALUE; } }
quelle
Weil es sich um verschiedene Typen handelt und aus praktischen Gründen. Leistung ist wahrscheinlich der Grund für primitive Typen.
quelle
Einige Datenstrukturen können nur Objekte akzeptieren, keine primitiven Typen.
Beispiel: Der Schlüssel in einer HashMap.
Weitere Informationen finden Sie in dieser Frage: HashMap und int als Schlüssel
Es gibt andere gute Gründe, z. B. ein "int" -Feld in einer Datenbank, das ebenfalls NULL sein kann. Ein int in Java kann nicht null sein. eine Integer-Referenz kann. Autoboxing und Unboxing bieten die Möglichkeit, das Schreiben von Fremdcode in die Konvertierungen hin und her zu vermeiden.
quelle
ArrayList unterstützt nicht nur primitive Typen, sondern auch Klassen. aber wir müssen primitive Typen verwenden, z. B. int, double usw.
ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted. ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.
Die Integer-Klasse umschließt einen Wert vom primitiven Typ int in einem Objekt. Daher wird der folgende Code akzeptiert.
ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.
Wir können einen Wert mit der Methode add (value) hinzufügen. Um einen String-Wert hinzuzufügen, sagen Sie "Hallo" im strArrayList-Code
strArrayList.add("Hello");
und füge einen int-Wert hinzu, sagen wir 54, wir können schreiben
intArrayList.add(54);
aber wenn wir intArrayList.add (54) schreiben; Compiler konvertieren in die folgende Zeile
intArrayList.add(Integer.valueOf(54));
Da intArrayList.add (54) auf Benutzerseite einfach und akzeptabler ist, erledigt der Compiler die harte Arbeit, nämlich "
intArrayList.add(Integer.valueOf(54));
es ist AutoBoxing".In ähnlicher Weise geben wir zum Abrufen des Werts einfach intArrayList.get (0) und die Compilerkonvertierung ein, in
<code>intArrayList.get(0).intValue();
die autoUnboxing ausgeführt wird.quelle
Autoboxing: Konvertieren eines primitiven Werts in ein Objekt der entsprechenden Wrapper-Klasse.
Unboxing: Konvertieren eines Objekts eines Wrapper-Typs in den entsprechenden Grundwert
// Java program to illustrate the concept // of Autoboxing and Unboxing import java.io.*; class GFG { public static void main (String[] args) { // creating an Integer Object // with value 10. Integer i = new Integer(10); // unboxing the Object int i1 = i; System.out.println("Value of i: " + i); System.out.println("Value of i1: " + i1); //Autoboxing of char Character gfg = 'a'; // Auto-unboxing of Character char ch = gfg; System.out.println("Value of ch: " + ch); System.out.println("Value of gfg: " + gfg); } }
quelle