Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 43 - Reflection

## 43.5 Arrays

- 43.5 Arrays
  - 43.5.1 Erzeugen von Arrays
  - 43.5.2 Zugriff auf Array-Elemente

### 43.5.1 Erzeugen von Arrays

Auch für das Erzeugen von Arrays und den Zugriff auf ihre Elemente stellt Reflection Mechanismen zur Verfügung. Wichtige Voraussetzung dafür ist, daß Arrays in Java Objekte sind und ein Array somit immer eine Instanz der Klasse `Object` ist, gleich welchen Typs seine Elemente sind. Alle Methoden zum dynamischen Zugriff auf Arrays sind in der Klasse `Array` gebündelt, die sich ebenfalls im Paket `java.lang.reflect` befindet. `Array` enthält ausschließlich statische Methoden, die sich grob in die beiden Gruppen Erzeugen von Arrays und Zugriff auf Array-Elemente einteilen lassen.

Um ein Array dynamisch zu erzeugen gibt es in `Array` zwei Methoden mit dem Namen `newInstance`:

    public static Object newInstance(Class componentType, int length)
      throws NegativeArraySizeException

    public static Object newInstance(Class componentType, int[] dimensions)
      throws IllegalArgumentException, NegativeArraySizeException
| java.lang.reflect.Array

Beide Methoden erwarten als erstes Argument ein Klassenobjekt, das den Typ der Array-Elemente bestimmt. Dieses kann mit der Methode `getClass` oder - wie in Abschnitt 43.3 gezeigt - mit der .TYPE- oder .class-Notation erzeugt werden. Als zweites Element wird entweder ein einzelner Wert des Typs `int` angegeben, wenn ein eindimensionales Array erzeugt werden soll. Er gibt die Anzahl der zu erzeugenden Array-Elemente an. Alternativ kann ein `int`-Array übergeben werden, dessen Elementzahl die Anzahl der Dimensionen des zu erzeugenden Arrays bestimmt. Jedes Element definiert seinerseits, wie viele Elemente die korrespondierende Dimension hat. Der Rückgabewert von `newInstance` ist das neu erzeugte Array, typisiert als `Object`.

Wir wollen uns ein einfaches Beispiel ansehen:

    001 /* Listing4308.java */
    002
    003 import java.lang.reflect.*;
    004
    005 public class Listing4308
    006 {
    007   public static void createArray1()
    008   {
    009     //Erzeugt ein eindimensionales int-Array
    010     Object ar = Array.newInstance(Integer.TYPE, 3);
    011     int[] iar = (int[])ar;
    012     for (int i = 0; i < iar.length; ++i) {
    013       iar[i] = i;
    014       System.out.println(iar[i]);
    015     };
    016   }
    017
    018   public static void createArray2()
    019   {
    020     //Erzeugt ein zweidimensionales String-Array
    021     Object ar = Array.newInstance(String.class, new int[]{7, 4});
    022     String[][] sar = (String[][])ar;
    023     for (int i = 0; i < sar.length; ++i) {
    024       for (int j = 0; j < sar[i].length; ++j) {
    025         sar[i][j] = "(" + i + "," + j + ")";
    026         System.out.print(sar[i][j] + " ");
    027       }
    028       System.out.println();
    029     };
    030   }
    031
    032   public static void main(String[] args)
    033   {
    034     createArray1();
    035     System.out.println("--");
    036     createArray2();
    037   }
    038 }
| Listing4308.java

Listing 43.8: Erzeugen von Arrays per Reflection

In Zeile 010 wird ein eindimensionales `int`-Array mit drei Elementen erzeugt, das zunächst vom Typ `Object` ist. Um zu zeigen, daß es sich tatsächlich um ein derartiges Array handelt, führen wir in der nächsten Zeile eine Typkonvertierung auf `int[]` durch und weisen es der Hilfsvariablen `iar` zu, auf der auch alle weiteren Zugriffe auf das Array erfolgen.

Analog wird in Zeile 021 ein weiteres Array erzeugt. Es ist ein zweidimensionales Array vom Typ `String`, das sieben Zeilen und vier Spalten besitzt. Auch hier wird in der nächsten Zeile eine Typkonvertierung vorgenommen, damit die anschließenden Zugriffe bequem erfolgen können. Die Ausgabe des Programms lautet:

    0
    1
    2
    --
    (0,0) (0,1) (0,2) (0,3)
    (1,0) (1,1) (1,2) (1,3)
    (2,0) (2,1) (2,2) (2,3)
    (3,0) (3,1) (3,2) (3,3)
    (4,0) (4,1) (4,2) (4,3)
    (5,0) (5,1) (5,2) (5,3)
    (6,0) (6,1) (6,2) (6,3)

### 43.5.2 Zugriff auf Array-Elemente

Während wir im vorigen Beispiel noch mit der schon aus Abschnitt 5.7.2 bekannten []-Notation auf die Elemente der per Reflection erzeugten Arrays zugegriffen haben, wollen wir uns in diesem Abschnitt ansehen, wie auch die Elementzugriffe vollkommen dynamisch durchgeführt werden können. Dazu stellt die Klasse `Array` folgende Methoden zur Verfügung:

    public static Object get(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void set(Object array, int index, object value)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static int getLength(Object array)
      throws IllegalArgumentException
| java.lang.reflect.Array

Mit `get` kann auf das Element mit dem Index `index` des Arrays `array` zugegriffen werden. Es wird stets als `Object` zurückgegeben, primitive Typen werden in ein Wrapper-Objekt verpackt. Die Methode `set` führt die umgekehrte Funktion aus. Sie speichert den Wert `value` an der durch `index` bezeichneten Position im Array `array`. Auch hier müssen primitive Werte vor der Übergabe in ein Wrapper-Objekt verpackt werden. Beide Methoden lösen eine Ausnahme aus, wenn das übergebene Objekt kein Array ist oder ein ungültiger Index angegeben wird. Schließlich gibt es die Methode `getLength`, mit der die Anzahl der Elemente eines Arrays ermittelt werden kann.

|  | Der Zugriff auf mehrdimensionale Arrays erfolgt analog dem statischen Fall. Auch hier gilt, daß mehrdimensionale Arrays als (ggfs. mehrfach) geschachtelte eindimensionale Arrays dargestellt werden (siehe Abschnitt 4.4.3). Soll also beispielsweise ein Element eines zweidimensionalen Arrays gelesen werden, so sind dazu zwei Aufrufe von `get` nötig. Der erste liefert das geschachtelte innere Array, der zweite wird auf eben dieses Array angewendet und liefert das gewünschte Element. Bei mehr als zwei Dimensionen sind entsprechend weitere `get`-Aufrufe nötig. |  |
Hinweis

Neben den einfachen `get`- und `set`-Methoden gibt es weitere, die eine automatische Konvertierung zu primitiven Datentypen durchführen:

    public static boolean getBoolean(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static byte getByte(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static char getChar(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static short getShort(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static int getInt(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static long getLong(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static float getFloat(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static double getDouble(Object array, int index)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setBoolean(Object array, int index, boolean z)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setByte(Object array, int index, byte b)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setChar(Object array, int index, char c)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setShort(Object array, int index, short s)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setInt(Object array, int index, int i)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setLong(Object array, int index, long l)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setFloat(Object array, int index, float f)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException

    public static void setDouble(Object array, int index, double d)
      throws IllegalArgumentException, ArrayIndexOutOfBoundsException
| java.lang.reflect.Array

Das folgende Beispiel zeigt die Anwendung der `get`- und `set`-Methoden auf ein dynamisch erzeugtes Array:

    001 /* Listing4309.java */
    002
    003 import java.lang.reflect.*;
    004
    005 public class Listing4309
    006 {
    007   public static void createArray1()
    008   {
    009     //Erzeugt ein eindimensionales int-Array
    010     Object ar = Array.newInstance(Integer.TYPE, 3);
    011     for (int i = 0; i < Array.getLength(ar); ++i) {
    012       Array.set(ar, i, new Integer(i));
    013       System.out.println(Array.getInt(ar, i));
    014     };
    015   }
    016
    017   public static void createArray2()
    018   {
    019     //Erzeugt ein zweidimensionales String-Array
    020     Object ar = Array.newInstance(String.class, new int[]{7, 4});
    021     for (int i = 0; i < Array.getLength(ar); ++i) {
    022       Object subArray = Array.get(ar, i);
    023       for (int j = 0; j < Array.getLength(subArray); ++j) {
    024         String value = "(" + i + "," + j + ")";
    025         Array.set(subArray, j, value);
    026         System.out.print(Array.get(subArray, j) + " ");
    027       }
    028       System.out.println();
    029     };
    030   }
    031
    032   public static void main(String[] args)
    033   {
    034     createArray1();
    035     System.out.println("--");
    036     createArray2();
    037   }
    038 }
| Listing4309.java

Listing 43.9: Zuriff auf Array-Elemente per Reflection

Der Hauptunterschied zum vorigen Beispiel liegt darin, daß die Elemente der Arrays nunmehr ausschließlich mit Methoden der Klasse `Array` gesetzt und abgefragt werden. In `createArray1` ist es nötig, den `int`-Wert beim Aufruf der `set`-Methode in einen `Integer`-Wrapper zu verpacken; das Auslesen erfolgt dagegen typkonform mit der Methode `getInt`.

In `createArray2` wird jedes Element des äußeren Arrays zunächst in der Variablen `subArray` gespeichert. Da das Hauptarray `ar` zweidimensional ist, stellt `subArray` de facto ein eindimensionales `String`-Array dar, auf das in den folgenden Zeilen direkt mit `get` und `set` zugegriffen werden kann.

Die Ausgabe des Programms ist identisch mit der des vorigen Beispiels:

    0
    1
    2
    --
    (0,0) (0,1) (0,2) (0,3)
    (1,0) (1,1) (1,2) (1,3)
    (2,0) (2,1) (2,2) (2,3)
    (3,0) (3,1) (3,2) (3,3)
    (4,0) (4,1) (4,2) (4,3)
    (5,0) (5,1) (5,2) (5,3)
    (6,0) (6,1) (6,2) (6,3)

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