Reflection (Java): Unterschied zwischen den Versionen
K (1 Versionen) |
K |
||
(2 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt) | |||
Zeile 12: | Zeile 12: | ||
Um mit Reflection zu arbeiten, benötigt man ein [[Class_(Java_API)|Class]]-Objekt desjenigen Typen, mit dem man arbeiten will. Dieses Objekt erhält man üblicherweise auf einem der folgenden Wege: | Um mit Reflection zu arbeiten, benötigt man ein [[Class_(Java_API)|Class]]-Objekt desjenigen Typen, mit dem man arbeiten will. Dieses Objekt erhält man üblicherweise auf einem der folgenden Wege: | ||
* Mittels dem Syntax "x.class", wobei "x" ein beliebiger Typ sein kann. | * Mittels dem Syntax "x.class", wobei "x" ein beliebiger Typ sein kann. | ||
− | < | + | <syntaxhighlight lang="java">Class<?> classString = String.class; |
Class<?> classInt = int.class; | Class<?> classInt = int.class; | ||
− | Class<?> classFloatArray = float[].class;</ | + | Class<?> classFloatArray = float[].class;</syntaxhighlight> |
* Mit der Methode "getClass", welche jedes Objekt besitzt. | * Mit der Methode "getClass", welche jedes Objekt besitzt. | ||
− | < | + | <syntaxhighlight lang="java">Object unknown = ... |
− | Class<?> classUnknown = unknown.getClass();</ | + | Class<?> classUnknown = unknown.getClass();</syntaxhighlight> |
* Über einen [[ClassLoader_(Java_API)|ClassLoader]], der diesen Typ kennt. | * Über einen [[ClassLoader_(Java_API)|ClassLoader]], der diesen Typ kennt. | ||
− | < | + | <syntaxhighlight lang="java">ClassLoader loader = ClassLoader.getSystemClassLoader(); |
− | Class<?> classFrame = loader.loadClass( "javax.swing.JFrame" );</ | + | Class<?> classFrame = loader.loadClass( "javax.swing.JFrame" );</syntaxhighlight> |
== Zugriff auf Informationen == | == Zugriff auf Informationen == | ||
Zeile 35: | Zeile 35: | ||
Im folgenden Beispiel wird ein Punkt erzeugt, und ausgegeben: | Im folgenden Beispiel wird ein Punkt erzeugt, und ausgegeben: | ||
− | < | + | <syntaxhighlight lang="java">Class<?> point = Class.forName( "java.awt.Point" ); |
Constructor<?> constructor = point.getConstructor( | Constructor<?> constructor = point.getConstructor( | ||
new Class[]{ int.class, int.class }); | new Class[]{ int.class, int.class }); | ||
Object object = constructor.newInstance( new Object[]{ 45, 97 }); | Object object = constructor.newInstance( new Object[]{ 45, 97 }); | ||
− | System.out.println( object );</ | + | System.out.println( object );</syntaxhighlight> |
== Aufrufe tätigen == | == Aufrufe tätigen == | ||
Zeile 50: | Zeile 50: | ||
== Restriktionen aushebeln == | == Restriktionen aushebeln == | ||
Das folgende Beispiel benutzt Reflection um auf den, eigentlich geschützten, char-[[Array]] eines [[String_(Java_API)|Strings]] zuzugreiffen. | Das folgende Beispiel benutzt Reflection um auf den, eigentlich geschützten, char-[[Array]] eines [[String_(Java_API)|Strings]] zuzugreiffen. | ||
− | < | + | <syntaxhighlight lang="java"> |
import java.lang.reflect.Field; | import java.lang.reflect.Field; | ||
Zeile 85: | Zeile 85: | ||
} | } | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
== Objekt herstellen und Methoden aufrufen == | == Objekt herstellen und Methoden aufrufen == | ||
Dieses Beispiel zeigt, wie eine Klasse, von der man nur den Namen kennt, und die garantiert noch nicht im System existiert, geladen wird. Danach wird eine [[Instanz]] dieser Klasse angelegt, und eine Methode aufgerufen. | Dieses Beispiel zeigt, wie eine Klasse, von der man nur den Namen kennt, und die garantiert noch nicht im System existiert, geladen wird. Danach wird eine [[Instanz]] dieser Klasse angelegt, und eine Methode aufgerufen. | ||
− | < | + | <syntaxhighlight lang="java">package hidden; |
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||
Zeile 218: | Zeile 218: | ||
0, 2, 0, 1, 0, 76, 0, 0, 0, 2, 0, 77 }; | 0, 2, 0, 1, 0, 76, 0, 0, 0, 2, 0, 77 }; | ||
} | } | ||
− | </ | + | </syntaxhighlight> |
[[Kategorie:Java]] | [[Kategorie:Java]] | ||
+ | [[Kategorie:Java Grundlagen]] |
Aktuelle Version vom 27. Juni 2022, 12:43 Uhr
Reflection in Java ist eine Möglichkeit, Informationen über Klassen, Methoden und andere Sprachelemente zu erhalten, ohne diese Elemente während dem Programmieren zu kennen.
Eine kleine Auswahl von Informationen:
- Eine Liste aller Methoden einer Klasse
- Die Argumente einer Methode
- Die Sichtbarkeit einer Variable
- Die Annotationen eines Elementes
Diese Informationen können auch dazu verwendet werden, Objekte einer bestimmten Klasse herzustellen, die Methoden des Objektes aufzurufen, oder Felder des Objektes abzuändern. Der Typ des Objektes muss wiederum nicht im vornherein bekannt sein.
Inhaltsverzeichnis
Arbeiten mit Reflection
Um mit Reflection zu arbeiten, benötigt man ein Class-Objekt desjenigen Typen, mit dem man arbeiten will. Dieses Objekt erhält man üblicherweise auf einem der folgenden Wege:
- Mittels dem Syntax "x.class", wobei "x" ein beliebiger Typ sein kann.
Class<?> classString = String.class;
Class<?> classInt = int.class;
Class<?> classFloatArray = float[].class;
- Mit der Methode "getClass", welche jedes Objekt besitzt.
Object unknown = ...
Class<?> classUnknown = unknown.getClass();
- Über einen ClassLoader, der diesen Typ kennt.
ClassLoader loader = ClassLoader.getSystemClassLoader();
Class<?> classFrame = loader.loadClass( "javax.swing.JFrame" );
Zugriff auf Informationen
Die Klasse Class bietet verschiedene Methoden mehr über die dargestellte Klasse herauszufinden. Das geht von dem Namen der Klasse ("getName"), über die Klasse von der geerbt wurde ("getSuperclass") bis zu allen Methoden ("getDeclaredMethods"), Konstruktoren ("getConstructors") und Feldern ("getFields").
Über einzelne Felder, Methoden, ... lassen sich dann wiederum zusätzliche Informationen abrufen, z.B. die Argumente eines Konstruktors.
Objekte generieren
Besitzt man erstmal die Klasse, will man meist auch ein Objekt dieser Klasse haben.
Dazu gibt es zwei einfache Wege:
- Direkt über die Methode "newInstance" von Class kann ein Objekt erzeugt werden. Das entspricht genau dem Verhalten, wie wenn man den Defaultkonstruktor aufrufen würde. Wenn kein solcher Konstruktor vorhanden ist, wird eine Exception geworfen.
- Über ein Constructor-Objekt, indem die Methode "newInstance" mit passenden Argumenten aufgerufen wird.
Im folgenden Beispiel wird ein Punkt erzeugt, und ausgegeben:
Class<?> point = Class.forName( "java.awt.Point" );
Constructor<?> constructor = point.getConstructor(
new Class[]{ int.class, int.class });
Object object = constructor.newInstance( new Object[]{ 45, 97 });
System.out.println( object );
Aufrufe tätigen
Mit Reflection kann man auch Methoden aufrufen oder Felder ändern.
- Anstelle des normalen Methodenaufrufes "object.x( y, z )" benutzt man das Method-Objekt, welches die Methode "x" darstellt, und ruft "x.invoke( object, x, y )" auf.
- Anstelle einer Zuweisung "object.x = y" benutzt man das Field-Objekt, welches "x" darstellt, und ruft "x.set( object, y )" auf.
Beispiele
Restriktionen aushebeln
Das folgende Beispiel benutzt Reflection um auf den, eigentlich geschützten, char-Array eines Strings zuzugreiffen.
import java.lang.reflect.Field;
public class Evil {
public static void main( String[] args ) throws Exception{
// Die Ausgabe dieses Programmes ist...
System.out.println( "Hallo Welt" );
// ... jedenfalls nicht "Hallo Welt"
}
static{
try{
// Repräsentation der String-Klasse abrufen
Class<String> clazz = String.class;
String object = "Hallo Welt";
String text = "Ich bin böse!";
// Zugriff auf die Felder "value" und "count" erlangen
Field value = clazz.getDeclaredField( "value" );
Field count = clazz.getDeclaredField( "count" );
// Die Sichtbarkeit der Felder von private auf public erhöhen
value.setAccessible( true );
count.setAccessible( true );
// Den Feldern neue Werte zuweisen
value.set( object, text.toCharArray() );
count.setInt( object, text.length() );
}
catch( Exception ex ){
ex.printStackTrace();
}
}
}
Objekt herstellen und Methoden aufrufen
Dieses Beispiel zeigt, wie eine Klasse, von der man nur den Namen kennt, und die garantiert noch nicht im System existiert, geladen wird. Danach wird eine Instanz dieser Klasse angelegt, und eine Methode aufgerufen.
package hidden;
import java.lang.reflect.Method;
public class Hidden {
public static void main( String[] args ) throws Exception{
Loader loader = new Loader();
Class<?> clazz = loader.loadClass( "hidden.Riddle" );
Object object = clazz.newInstance();
Method run = clazz.getMethod( "run", new Class[0] );
run.invoke( object, new Object[0] );
}
private static class Loader extends ClassLoader{
@Override
protected Class<?> findClass( String name ) throws ClassNotFoundException {
if( name.equals( "hidden.Riddle" )){
return defineClass( "hidden.Riddle", CODE, 0, CODE.length );
}
else
return super.findClass( name );
}
}
public static final byte[] CODE = {
-54, -2, -70, -66, 0, 0, 0, 49, 0, 78, 7,
0, 2, 1, 0, 13, 104, 105, 100, 100, 101, 110,
47, 82, 105, 100, 100, 108, 101, 7, 0, 4, 1,
0, 16, 106, 97, 118, 97, 47, 108, 97, 110, 103,
47, 79, 98, 106, 101, 99, 116, 1, 0, 5, 118,
97, 108, 117, 101, 1, 0, 1, 73, 1, 0, 6,
60, 105, 110, 105, 116, 62, 1, 0, 3, 40, 41,
86, 1, 0, 4, 67, 111, 100, 101, 10, 0, 3,
0, 11, 12, 0, 7, 0, 8, 10, 0, 13, 0,
15, 7, 0, 14, 1, 0, 14, 106, 97, 118, 97,
47, 108, 97, 110, 103, 47, 77, 97, 116, 104, 12,
0, 16, 0, 17, 1, 0, 6, 114, 97, 110, 100,
111, 109, 1, 0, 3, 40, 41, 68, 6, 64, 89,
0, 0, 0, 0, 0, 0, 9, 0, 1, 0, 21,
12, 0, 5, 0, 6, 1, 0, 15, 76, 105, 110,
101, 78, 117, 109, 98, 101, 114, 84, 97, 98, 108,
101, 1, 0, 18, 76, 111, 99, 97, 108, 86, 97,
114, 105, 97, 98, 108, 101, 84, 97, 98, 108, 101,
1, 0, 4, 116, 104, 105, 115, 1, 0, 15, 76,
104, 105, 100, 100, 101, 110, 47, 82, 105, 100, 100,
108, 101, 59, 1, 0, 3, 114, 117, 110, 7, 0,
28, 1, 0, 17, 106, 97, 118, 97, 47, 117, 116,
105, 108, 47, 83, 99, 97, 110, 110, 101, 114, 9,
0, 30, 0, 32, 7, 0, 31, 1, 0, 16, 106,
97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 121,
115, 116, 101, 109, 12, 0, 33, 0, 34, 1, 0,
2, 105, 110, 1, 0, 21, 76, 106, 97, 118, 97,
47, 105, 111, 47, 73, 110, 112, 117, 116, 83, 116,
114, 101, 97, 109, 59, 10, 0, 27, 0, 36, 12,
0, 7, 0, 37, 1, 0, 24, 40, 76, 106, 97,
118, 97, 47, 105, 111, 47, 73, 110, 112, 117, 116,
83, 116, 114, 101, 97, 109, 59, 41, 86, 9, 0,
30, 0, 39, 12, 0, 40, 0, 41, 1, 0, 3,
111, 117, 116, 1, 0, 21, 76, 106, 97, 118, 97,
47, 105, 111, 47, 80, 114, 105, 110, 116, 83, 116,
114, 101, 97, 109, 59, 8, 0, 43, 1, 0, 38,
71, 105, 98, 32, 101, 105, 110, 101, 32, 90, 97,
104, 108, 32, 122, 119, 105, 115, 99, 104, 101, 110,
32, 48, 32, 117, 110, 100, 32, 49, 48, 48, 32,
101, 105, 110, 58, 32, 10, 0, 45, 0, 47, 7,
0, 46, 1, 0, 19, 106, 97, 118, 97, 47, 105,
111, 47, 80, 114, 105, 110, 116, 83, 116, 114, 101,
97, 109, 12, 0, 48, 0, 49, 1, 0, 5, 112,
114, 105, 110, 116, 1, 0, 21, 40, 76, 106, 97,
118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114,
105, 110, 103, 59, 41, 86, 10, 0, 27, 0, 51,
12, 0, 52, 0, 53, 1, 0, 10, 104, 97, 115,
78, 101, 120, 116, 73, 110, 116, 1, 0, 3, 40,
41, 90, 10, 0, 27, 0, 55, 12, 0, 56, 0,
57, 1, 0, 7, 110, 101, 120, 116, 73, 110, 116,
1, 0, 3, 40, 41, 73, 8, 0, 59, 1, 0,
7, 82, 105, 99, 104, 116, 105, 103, 10, 0, 45,
0, 61, 12, 0, 62, 0, 49, 1, 0, 7, 112,
114, 105, 110, 116, 108, 110, 8, 0, 64, 1, 0,
16, 70, 97, 108, 115, 99, 104, 44, 32, 122, 117,
32, 107, 108, 101, 105, 110, 8, 0, 66, 1, 0,
16, 70, 97, 108, 115, 99, 104, 44, 32, 122, 117,
32, 103, 114, 111, 115, 115, 8, 0, 68, 1, 0,
24, 68, 97, 115, 32, 115, 111, 108, 108, 32, 101,
105, 110, 101, 32, 90, 97, 104, 108, 32, 115, 101,
105, 110, 63, 10, 0, 27, 0, 70, 12, 0, 71,
0, 72, 1, 0, 4, 110, 101, 120, 116, 1, 0,
20, 40, 41, 76, 106, 97, 118, 97, 47, 108, 97,
110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 1,
0, 1, 115, 1, 0, 19, 76, 106, 97, 118, 97,
47, 117, 116, 105, 108, 47, 83, 99, 97, 110, 110,
101, 114, 59, 1, 0, 5, 99, 104, 101, 99, 107,
1, 0, 10, 83, 111, 117, 114, 99, 101, 70, 105,
108, 101, 1, 0, 11, 82, 105, 100, 100, 108, 101,
46, 106, 97, 118, 97, 0, 33, 0, 1, 0, 3,
0, 0, 0, 1, 0, 2, 0, 5, 0, 6, 0,
0, 0, 2, 0, 1, 0, 7, 0, 8, 0, 1,
0, 9, 0, 0, 0, 67, 0, 5, 0, 1, 0,
0, 0, 17, 42, -73, 0, 10, 42, -72, 0, 12,
20, 0, 18, 107, -114, -75, 0, 20, -79, 0, 0,
0, 2, 0, 22, 0, 0, 0, 14, 0, 3, 0,
0, 0, 5, 0, 4, 0, 6, 0, 16, 0, 5,
0, 23, 0, 0, 0, 12, 0, 1, 0, 0, 0,
17, 0, 24, 0, 25, 0, 0, 0, 1, 0, 26,
0, 8, 0, 1, 0, 9, 0, 0, 0, -33, 0,
3, 0, 3, 0, 0, 0, 105, -69, 0, 27, 89,
-78, 0, 29, -73, 0, 35, 76, -78, 0, 38, 18,
42, -74, 0, 44, 43, -74, 0, 50, -103, 0, 65,
43, -74, 0, 54, 61, 28, 42, -76, 0, 20, -96,
0, 14, -78, 0, 38, 18, 58, -74, 0, 60, -89,
0, 57, 28, 42, -76, 0, 20, -94, 0, 14, -78,
0, 38, 18, 63, -74, 0, 60, -89, -1, -55, 28,
42, -76, 0, 20, -92, -1, -63, -78, 0, 38, 18,
65, -74, 0, 60, -89, -1, -74, -78, 0, 38, 18,
67, -74, 0, 60, 43, -74, 0, 69, 87, -89, -1,
-90, -79, 0, 0, 0, 2, 0, 22, 0, 0, 0,
62, 0, 15, 0, 0, 0, 9, 0, 11, 0, 11,
0, 19, 0, 12, 0, 26, 0, 13, 0, 31, 0,
14, 0, 39, 0, 15, 0, 47, 0, 16, 0, 50,
0, 18, 0, 58, 0, 19, 0, 69, 0, 21, 0,
77, 0, 22, 0, 88, 0, 26, 0, 96, 0, 27,
0, 101, 0, 30, 0, 104, 0, 31, 0, 23, 0,
0, 0, 32, 0, 3, 0, 0, 0, 105, 0, 24,
0, 25, 0, 0, 0, 11, 0, 94, 0, 73, 0,
74, 0, 1, 0, 31, 0, 57, 0, 75, 0, 6,
0, 2, 0, 1, 0, 76, 0, 0, 0, 2, 0, 77 };
}