Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 10 - OOP IV: Verschiedenes

## 10.2 Wrapper-Klassen

- 10.2 Wrapper-Klassen
  - 10.2.1 Vordefinierte Wrapper-Klassen
    - Instanzierung
    - Rückgabe des Wertes
    - Parsen von Strings
    - Konstanten
  - 10.2.2 Call by Reference

### 10.2.1 Vordefinierte Wrapper-Klassen

Zu jedem primitiven Datentyp in Java gibt es eine korrespondierende Wrapper-Klasse. Diese kapselt die primitive Variable in einer objektorientierten Hülle und stellt eine Reihe von Methoden zum Zugriff auf die Variable zur Verfügung. Zwar wird man bei der Programmierung meist die primitiven Typen verwenden, doch gibt es einige Situationen, in denen die Anwendung einer Wrapper-Klasse sinnvoll sein kann:

- Das Paket `java.util` stellt eine Reihe von Verbundklassen zur Verfügung, die beliebige Objekttypen speichern können. Um darin auch elementare Typen ablegen zu können, ist es notwendig, anstelle der primitiven Typen ihre Wrapper-Klassen zu verwenden.
- Da Objektreferenzen den Wert `null` haben können, kann die Verwendung der Wrapper-Klassen beispielsweise bei der Datenbankprogrammierung nützlich sein. Damit lassen sich primitive Feldtypen darstellen, die NULL-Werte enthalten können.
- Das Reflection-API (siehe Kapitel 43) verwendet Wrapper-Klassen zum Zugriff auf Membervariablen oder Methodenargumente primitiver Typen.

Wrapper-Klassen existieren zu allen numerischen Typen und zu den Typen `char` und `boolean`:

Wrapper-Klasse | Primitiver Typ
`Byte` | `byte`
`Short` | `short`
`Integer` | `int`
`Long` | `long`
`Double` | `double`
`Float` | `float`
`Boolean` | `boolean`
`Character` | `char`
`Void` | `void`

Tabelle 10.1: Die Wrapper-Klassen

#### Instanzierung

Die Instanzierung einer Wrapper-Klasse kann meist auf zwei unterschiedliche Arten erfolgen. Einerseits ist es möglich, den korrespondierenden primitiven Typ an den Konstruktor zu übergeben, um ein Objekt desselben Werts zu erzeugen. Alternativ kann meist auch ein String an den Konstruktor übergeben werden. Dieser wird in den entsprechenden primitiven Typ konvertiert und dann zur Initialisierung der Wrapper-Klasse verwendet.

    public Integer(int i)

    public Integer(String s)
      throws NumberFormatException

    public Long(long l)

    public Long(String s)
      throws NumberFormatException

    public Float(float f)

    public Float(double d)

    public Float(String s)
      throws NumberFormatException

    public Double(double d)

    public Double(String s)
      throws NumberFormatException

    public Boolean(boolean b)

    public Boolean(String s)

    public Character(char c)

|  | Das in diesem Beispiel mehrfach verwendete Schlüsselwort `throws` deklariert Ausnahmen, die während der Methodenausführung auftreten können. Sie entstehen durch Programmfehler, undefinierte Zustände oder treten auf, wenn unvorhergesehene Ereignisse eintreten (Datei nicht verfügbar, Speicher erschöpft oder ähnliches). Wir werden uns in Kapitel 12 ausführlich mit diesem Thema beschäftigen. |  |
Hinweis

#### Rückgabe des Wertes

Die meisten Wrapper-Klassen besitzen zwei Methoden, um den internen Wert abzufragen. Eine der beiden liefert ihn passend zum korrespondierenden Grundtyp, die andere als `String`. Der Name von Methoden der ersten Art setzt sich aus dem Namen des Basistyps und der Erweiterung `Value` zusammen, beispielsweise `charValue`, `booleanValue` oder `intValue`. Die numerischen Methoden `intValue`, `longValue`, `floatValue` und `doubleValue` stehen dabei für alle numerischen Wrapper-Klassen zur Verfügung.

    public boolean booleanValue()
    public char charValue()
    public int intValue()
    public long longValue()
    public float floatValue()
    public double doubleValue()

Der Name der Methode, die den internen Wert als `String` zurückgibt, ist `toString`. Diese Methode steht in allen Wrapper-Klassen zur Verfügung:

    public String toString()

#### Parsen von Strings

Neben der Möglichkeit, aus Strings Objekte zu erzeugen, können die meisten Wrapper-Klassen auch primitive Datentypen erzeugen. Dazu gibt es statische Methoden mit den Namen `parseByte`, `parseInt`, `parseLong`, `parseFloat` und `parseDouble` in den zugehörigen Klassen `Byte`, `Integer`, `Long`, `Float` und `Double`:

    public static byte parseByte(String s)
      throws NumberFormatException

    public static int parseInt(String s)
      throws NumberFormatException

    public static long parseLong(String s)
      throws NumberFormatException

    public static float parseFloat(String s)
      throws NumberFormatException

    public static double parseDouble(String s)
      throws NumberFormatException

|  |  |  | Die Methoden `parseFloat` und `parseDouble` gibt es erst seit dem JDK 1.2. In älteren JDK-Versionen und den meisten Web-Browsern stehen sie nicht zur Verfügung. |  |
JDK1.1-1.4

#### Konstanten

Die numerischen Wrapper-Klassen stellen Konstanten zur Bezeichnung spezieller Elemente zur Verfügung. So gibt es in jeder der Klassen `Byte`, `Short`, `Integer`, `Long`, `Float` und `Double` die Konstanten `MIN_VALUE` und `MAX_VALUE`, die das kleinste bzw. größte Element des Wertebereichs darstellen. In den Klassen `Float` und `Double` gibt es zusätzlich die Konstanten `NEGATIVE_INFINITY`, `POSITIVE_INFINITY` und `NaN`. Sie stellen die Werte minus unendlich, plus unendlich und undefiniert dar.

### 10.2.2 Call by Reference

Da Objektparameter im Gegensatz zu primitiven Typen per Referenz übergeben werden, wären Wrapper-Klassen prinzipiell geeignet, Methodenparameter per call by reference zu übergeben. Damit könnten Änderungen von primitiven Parametern an den Aufrufer zurückgegeben werden. In der Praxis funktioniert das allerdings nicht, denn alle vordefinierten Wrapper-Klassen sind unveränderlich (das wird auch als immutable bezeichnet).

Sollen primitive Typen per Referenz übergeben werden, bieten sich zwei Möglichkeiten an:

- Der primitive Typ kann in einen eigenen Wrapper verpackt werden, der das Ändern des Wertes erlaubt.
- Der primitive Typ kann als Element eines Array übergeben werden. Da Arrays Objekte sind und somit stets per Referenz übergeben werden, sind Änderungen an ihren Elementen auch für den Aufrufer sichtbar.

Beide Methoden sind nicht sehr elegant, werden aber in der Praxis mitunter benötigt. Das folgende Listing zeigt, wie es gemacht wird:

    001 /* Listing1005.java */
    002
    003 class IntWrapper
    004 {
    005   public int value;
    006
    007   public IntWrapper(int value)
    008   {
    009     this.value = value;
    010   }
    011 }
    012
    013 public class Listing1005
    014 {
    015   public static void inc1(IntWrapper w)
    016   {
    017     ++w.value;
    018   }
    019
    020   public static void inc2(int[] i)
    021   {
    022     ++i[0];
    023   }
    024
    025   public static void main(String[] args)
    026   {
    027     //Variante 1: Übergabe in einem veränderlichen Wrapper
    028     IntWrapper i = new IntWrapper(10);
    029     System.out.println("i = " + i.value);
    030     inc1(i);
    031     System.out.println("i = " + i.value);
    032     //Variante 2: Übergabe als Array-Element
    033     int[] j = new int[] {10};
    034     System.out.println("j = " + j[0]);
    035     inc2(j);
    036     System.out.println("j = " + j[0]);
    037   }
    038 }
| Listing1005.java

Listing 10.5: Call by Reference

Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0
<< | < | > | >> | API | © 1998-2002 Guido Krüger, http://www.javabuch.de