Living in a Box: Boxing primitiver Datentypen in Java
Dieser Artikel wurde von Tobias Nebel geschrieben.
Tobias Nebel hat sein Studium der Telekommunikationsinformatik an der Hochschule für Telekommunikation in Leipzig absolviert. Er arbeitet als Softwareentwickler bei der Firma ubigrate mit dem Schwerpunkt Geräteintegration.
Viele objektorientierte Programmiersprachen wie Java behandeln Daten als Objekte, welche ihrerseits Instanzen von Klassen darstellen. Jedes Objekt ist dabei eindeutig über seine Referenz identifizierbar. Beim Aufruf einer Methode werden nicht die Objekte selbst übergeben, sondern nur deren Referenzen. Eine Zugriff auf das Objekt mittels der übergebenen Referenz ist daher von überall aus durchführbar.
Dennoch kennt Java aufgrund seiner Abstammung aus der C-Familie auch primitive Datentypen wie int, long, float, double etc. Wird einer Methode ein Argument eines primitiven Datentypens übergeben, erhält diese jedoch keine Referenz, sondern nur den Wert der Variablen (call-by-value). Primitive Datentypen können mit der Hilfe spezieller Klassen wie Integer, Long , Float, Double usw. in Objekte verwandelt werden. Diese Klassen werden Wrapper genannt. Den Vorgang des Ein- und Auspackens der primitiven Variablen in Wrapper bezeichnet man als boxing bzw. unboxing. Boxing und unboxing sind z.B. erforderlich, wenn primitive Datentypen in einer Liste gespeichert werden sollen, da die von Java zur Verfügung gestellten Containerklassen nur Objekte unterstützen.
Trotz oben erwähnter Übergabe der Objektreferenzen findet in Java kein call-by-reference der Argumente statt – auch die Referenzen werden per call-by-value übergeben. Das folgende Codebeispiel soll dies verdeutlichen:
public void foo( Person p )
{
p = new Person( "Eva" );
}
Person person = new Person( "Adam" );
foo( person );
person.getName(); // Objekt 'person' hat
// immer noch den Wert "Adam"
das Objekt kann jedoch wie folgt verändert werden:
public void foo( Person p )
{
p.setName( "Eva" );
}
Person person = new Person( "Adam" );
foo( person );
person.getName(); // Objekt 'person'
// hat jetzt den Wert "Eva"
oder:
public Person foo( Person p )
{
p = new Person( "Eva" );
return p;
}
Person person = new Person( "Adam" );
person = foo( person );
person.getName(); // Objekt 'person'
// hat jetzt den Wert "Eva"
Scott Stanchfield beschreibt diesen Umstand genauer in einem seiner Artikel.
Seit der Version 1.5 unterstützt Java automatisches Boxing bzw. Unboxing. Das bedeutet, dass der Compiler automatisch das Wrappen von primitiven Datentypen in die entsprechenden Objekte übernimmt.
Das Erzeugen von Integer-Objekten ist auf verschiedene Art und Weisen möglich:
// "alt": int i = 23; Integer iA = new Integer( i ); Integer iB = Integer.valueOf( i ); int ia = ia.intValue(); // "neu" (Auto-Boxing): Integer iC = i; Object obj = 5; int ib = iC; int ic = (Integer) obj;
Bei der Erzeugung von Wrapper-Objekten gilt es jedoch einiges zu beachten:
Beispielsweise werden für Objekte vom Typ Integer mit einem Wert im Bereich -128…127 gecachte (und somit bereits erzeugte) Integer-Instanzen zurückgegeben. Folgende Code-Zeilen sollen das verdeutlichen:
int a=23;
int b=23;
Integer iA = a; // entspricht Integer.valueOf,
// gibt gecachte Instanz zurück
Integer iB = b; // entspricht Interger.valueOf,
// gibt gecachte Instanz zurück
Integer iAA = new Integer( a ); // erzeugt "echtes"
// neues Objekt
Integer iAAA = new Integer( a ); // erzeugt "echtes"
// neues Objekt
Integer iBB = new Integer( b ); // erzeugt "echtes"
// neues Objekt
boolean b = iA==iB; // true
b = iAA==iBB; // false
b = iAA==iAAA; // false
iAA.equals( iBB ); // true
iAA.equals( iAAA ); // true
--------------------------------------------------------
int a=235;
int b=235;
Integer iA = a; // Wert > 127,
// also wird neue Instanz erzeugt
Integer iB = b; // Wert > 127,
// also wird neue Instanz erzeugt
boolean b = iA==iB; // false
b = iA.equals( iB ); // true
Dieses Verhalten ist nicht unbedingt gleich so zu erwarten und kann hier und da schon mal zu Verwirrung führen.
Fazit
Auto-Boxing bringt Vorteile beim Schreiben von Programmmen, zieht jedoch einige Einschränkungen nach sich. Zu beachten ist, dass die Referenz einer in ein Wrapper-Objekt “eingewickelten” primitiven Variable derer eines anderen Wrapper-Objektes mit dem gleichen Wert entspricht. Demnach kann Auto-Boxing nicht zur zweifelsfreien Identifizierung einer primitiven Variable benutzt werden, sondern nur zum Vergleich derer Werte.
























Patrik Spieß sagt
am 26. Juni 2008 @ 11:30
Die Codefragmente sind leider nicht lesbar, da sie ungefähr fünf mal so breit sind wie die Seite und daher sehr weit rechts herausragen.
Gruß,
Patrik
Tobias sagt
am 26. Juni 2008 @ 12:52
Danke für den Hinweis. Da sind wohl irgendwie alle Zeilenumbrüche abhanden gekommen. Jetzt sollte es aber wieder lesbar sein.
Grüße, Tobias