Reflection API jenseits Class
Erzeugen von Instanzen
- Instanzen werden über
ConstructorObjekte erzeugt - Man holt sich von
Classden passenden Konstruktor mitConstructor<T> getConstructor(Class<?>... parameterTypes) - Neue Instanzen werden erzeugt mit
newInstance(Object... params)
- Mögliche Ausnahmen
SecurityException– Code darf keine Reflection machenNoSuchMethodException– Es gibt den Konstruktor nichtIllegalArgumentException– Argumente passen nichtInstantiationException– Klasse ist abstraktIllegalAccessException– Konstruktor ist nicht publicInvocationTargetException– Konstruktor wirft selbst eine Exception
Beispiel: Instanz erzeugen
try {
Constructor<Date> constructor
= clazz.getConstructor(long.class);
Object o = constructor.newInstance(222222222222L);
System.out.println(o); // -> Sun Jan 16 01:23:42 CET 1977
} catch (SecurityException e) {
// darf keine Reflection machen
} catch (NoSuchMethodException e) {
// es gibt den Construktor nicht
} catch (IllegalArgumentException e) {
// Argumente passen nicht
} catch (InstantiationException e) {
// Klasse ist abstrakt
} catch (IllegalAccessException e) {
// Konstruktor ist nicht public
} catch (InvocationTargetException e) {
// Konstruktor wirft selbst eine Exception
}
Aufrufen von Methoden
- Methoden werden über
Method-Objekte gerufen - Man holt sich von
Classdie passende Methode mitMethod getMethod(Class<?>... parameterTypes) - Die Methode wird aufgerufen mit
invoke(Object o, Object... params) - Mögliche Ausnahmen
SecurityException– Code darf keine Reflection machenNoSuchMethodException– Es gibt die Methode nichtIllegalArgumentException– Argumente passen nichtIllegalAccessException– Methode ist nicht publicInvocationTargetException– Methode wirft selbst eine Exception
Beispiel: Methoden aufrufen
Class<?> clazz = Integer.class;
Method m = clazz.getMethod("toHexString", int.class);
String result = (String) m.invoke(null, 255);
System.out.println(result); // -> ff
String s = "Hello ";
Class<?> clazz = s.getClass();
Method m = clazz.getMethod("concat", String.class);
Object result = m.invoke(s, "World!");
System.out.println(result); // -> Hello World!
Felder lesen und schreiben
- Felder werden über
FieldObjekte manipuliert - Man holt sich von
Classdas passende Feld mitField getField(String name) - Die Felder können dann mainpuliert werden mit
get(Object o) und set(Object o, Object value) - Für gängige Datentypen gibt es Hilfsmethoden (
setInt(...)etc.) - Mögliche Ausnahmen
SecurityException– Code darf keine Reflection machenNoSuchFieldException– Es gibt das Feld nichtIllegalArgumentException– Argumente passen nichtIllegalAccessException– Feld ist nicht public
Beispiel: Felder manipulieren
Class<Integer> clazz = Integer.class;
Field field = clazz.getField("MAX_VALUE");
int value = field.getInt(null);
System.out.println(value); // -> 2147483647
Point point = new Point();
Class<?> clazz = point.getClass();
Field fieldX = clazz.getField("x");
Field fieldY = clazz.getField("y");
fieldX.setInt(point, 640);
fieldY.setInt(point, 480);
System.out.println(point); // -> java.awt.Point[x=640,y=480]
Arrays
- Für Arrays gibt es keine eigenen
ClassObjekte, man benutzt das Objekt des Elementtyps - Arrays werden über die Klasse
Arrayund deren statische Methoden manipuliert Object newInstance(Class<?> componentType, int length)Object newInstance(Class<?> componentType,int... dimensions)int getLength(Object array)Object get(Object array, int index)void set(Object array, int index, Object value)
Beispiel: Arrays und Reflection
Class<String> elementTyp = String.class;
Object arrayInstanz = Array.newInstance(elementTyp, 4);
Array.set(arrayInstanz, 0, "Erster Eintrag");
Array.set(arrayInstanz, 1, "Zweiter Eintrag");
Array.set(arrayInstanz, 2, "Dritter Eintrag");
Array.set(arrayInstanz, 3, "Vierter Eintrag");
int length = Array.getLength(arrayInstanz);
for (int i = 0; i < length; i++) {
Object element = Array.get(arrayInstanz, i);
System.out.println(element);
}
Die dunkele Seite von Reflection
// Don't try this at home!!!
String immutable = "immutable String";
System.out.println(immutable);
System.out.println(immutable.hashCode());
Class<? extends String> clazz = immutable.getClass();
Field valueField = clazz.getDeclaredField("value");
valueField.setAccessible(true);
char[] chars = (char[]) valueField.get(immutable);
chars[0] = ' ';
chars[1] = ' ';
System.out.println(immutable);
System.out.println(immutable.hashCode());
Dieser Code zeigt, dass man mit Reflection Dinge tun kann, die normalerweise nicht möglich sind, z. B. den inneren Zustand eines Strings ändern. Solche Konstrukte sind ausgesprochen gefährlich und können bis zum Absturz der VM führen.