Wrapper-Klassen

Wrapper-Klassen

  • Primitive Typen sind keine Objekte
  • An manchen Stellen muss man aber Objekte anstatt primitiver Typen verwenden
  • Wrapper-Klassen (wrapper classes) stellen für jeden primitiven Typ einen passenden Klassen-Typ zur Verfügung
Primitiver Typ Wrapper
boolean Boolean
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double

Die Wrapper (Einwickler) haben ihren Namen von der Tatsache, dass sie sich um die primitiven Typen herum legen und sie als Objekt umschließen. Man beachte die Asymmetrie bei int/Integer und char/Character: Normalerweise entspricht der Name des Wrappers dem Namen des primitiven Typs nur mit Großbuchstaben. Bei int und char ist dem aber nicht so.

Alle Wrapper enthalten Konvertierungsmethoden in beide Richtungen, d. h. vom primitiven Typen zum Objekt und vom Objekt zum primitiven Typen.

Weiterhin finden sich in den Wrappern wichtige Konstanten, z. B. Integer.MAX_INT als maximaler Wert, den ein int annehmen kann.

Alle Wrapper sind als unveränderliche Objekte (immutable Objects) konstruiert. Es kann daher aus Performance-Gründen sinnvoll sein, ein und dasselbe Wrapper-Objekt mehrfach zu verwenden. Bei Boolean sollte man normalerweise überhaupt kein Wrapper-Objekt neu anlegen, sondern einfach die beiden vordefinierten Objekte Boolean.TRUE und Boolean.FALSE verwenden.

Beispiel: Wrapper

int i = 5;
Integer i1 = new Integer(i);
int j = i1.intValue();

Integer i2 = Integer.valueOf("42");
int i3 = Integer.parseInt("42");

Das Beispiel zeigt das Anlegen eines int-Wrappers über den Konstruktor von Integer und das Auslesen des Wertes aus dem Wrapper mit der Methode intValue(). Zusätzlich sind zwei Methoden gezeigt, um aus einem String einen int-Wert bzw. ein Integer-Objekt zu erzeugen. Die Verwendung des Konstruktors ist inzwischen nicht mehr empfohlen, sondern man sollte sich auf das Autoboxing stützen.

Autoboxing

Seit Java 5 kann der Compiler automatisch zwischen primitiven Typen und Klassen-Typen konvertieren, man spricht hier von Autoboxing

Integer k = 5;
int j = k;

Object o = true;
boolean b = new Boolean(true);

Long l = 0L;

for (int i = 0; i < Integer.MAX_VALUE; i++) {
    l += i;
}

Der Java-Compiler führt das Autoboxing in beiden Richtungen durch, d. h. es gibt sowohl ein autoboxing als auch ein auto-unboxing.

Die untere Schleife ist mit einem erheblichen Performanceproblem belastet.

Dadurch, dass man statt long Long geschrieben hat, findet bei jedem Schleifendurchlauf ein Autoboxing statt. Statt also einfach eine long-Variable zu erhöhen, werden hier mehrere Milliarden Long-Objekte erzeugt und wieder zerstört. Die Geschwindigkeit ist daher um Größenordnungen geringer, ohne dass man dies am Source-Code sehen könnte (bis auf das große „L“).

Praxistipp: Autoboxing und ==

  • Durch Autoboxing werden primitiven Typen zu Objekten. Damit gelten aber die Regeln für equals() und ==
  • Ein Vergleich von Wrapper-Typen mit == ist immer falsch
public static boolean compare(Integer i1, Integer i2) {
    return i1 == i2;
}

public static void main(String[] args) {
    int i1 = 10;
    int i2 = 10;
    System.out.println(i1 + " == " + i2 + " : " + compare(i1, i2));

    i1 = 2000;
    i2 = 2000;
    System.out.println(i1 + " == " + i2 + " : " + compare(i1, i2));
  }
Ausgabe
10 == 10 : true
2000 == 2000 : false

Die Ausgabe des Programms ist erstaunlich. Beim Wert 2000 sieht man deutlich, dass durch das Autoboxing der int-Variablen zwei unterschiedliche Objekte entstanden sind, die nicht damit nicht identisch sind. Daher liefert der ==-Vergleich false zurück.

Aber warum passiert das nicht bei dem Wert 10?

Die Klasse Integer nimmt eine Optimierung vor: für alle Werte kleiner 128 werden keine neuen Integer-Objekte erzeugt, sondern aus einem Cache einfach immer wieder dieselbe Objektreferenz zurückgeliefert. Dies ist möglich, da Integer unveränderlich (immutable) ist und daher für den Verwender nicht unterscheidbar ist, ob er zwei Referenzen auf zwei Objekte oder zwei Referenzen auf dasselbe Objekt benutzt (zumindest so lange er nicht mit == explizit darauf testet). Das hier von Integer angewandte Entwurfsmuster ist das sogenannte Fliegengewicht) (flyweight).


Copyright © 2025 Thomas Smits