Titel   Inhalt   Suchen   Index   DOC  Handbuch der Java-Programmierung, 7. Auflage
 <<    <     >    >>   API  Kapitel 45 - Reflection

45.5 Arrays



45.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, dass 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 45.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 /* Listing4508.java */
002 
003 import java.lang.reflect.*;
004 
005 public class Listing4508
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 }
Listing4508.java
Listing 45.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, dass 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)

45.5.2 Zugriff auf Array-Elemente

Während wir im vorigen Beispiel noch mit der schon aus Abschnitt 6.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. Auch hier gilt, dass mehrdimensionale Arrays als (ggfs. mehrfach) geschachtelte eindimensionale Arrays dargestellt werden (siehe Abschnitt 5.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.

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 /* Listing4509.java */
002 
003 import java.lang.reflect.*;
004 
005 public class Listing4509
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 }
Listing4509.java
Listing 45.9: Zugriff auf Array-Elemente per Reflection

Der Hauptunterschied zum vorigen Beispiel liegt darin, dass 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, 7. Auflage, Addison Wesley, Version 7.0
 <<    <     >    >>   API  © 1998, 2011 Guido Krüger & Heiko Hansen, http://www.javabuch.de