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