Java Reflection bietet die Möglichkeit, das Laufzeitverhalten einer Anwendung zu inspizieren und zu modifizieren. Reflexion in Java ist eines der fortgeschrittenen Themen des Kern-Java. Mit Java-Reflexion können wir eine Klasse, ein Interface, ein Enum inspizieren, ihre Struktur, Methoden und Feldinformationen zur Laufzeit abrufen, auch wenn die Klasse zur Kompilierungszeit nicht zugänglich ist. Wir können auch Reflexion verwenden, um ein Objekt zu instanziieren, seine Methoden aufzurufen und Feldwerte zu ändern.
Java Reflection
- Reflexion in Java
- Java Reflection für Klassen
- Klassenobjekt erhalten
- Superklasse erhalten
- Öffentliche Member-Klassen erhalten
- Deklarierte Klassen erhalten
- Deklarierende Klasse erhalten
- Paketnamen erhalten
- Klassenmodifier erhalten
- Typparameter erhalten
- Implementierte Schnittstellen erhalten
- Alle öffentlichen Methoden erhalten
- Alle öffentlichen Konstruktoren erhalten
- Alle öffentlichen Felder erhalten
- Alle Annotationen erhalten
- Java-Reflexion für Felder
- Java-Reflexion für Methoden
- Java-Reflexion für Konstruktoren
- Java-Reflexion für Annotationen
Die Reflexion in Java ist ein sehr mächtiges Konzept und es ist in der normalen Programmierung von geringem Nutzen, aber es ist das Rückgrat für die meisten Java- und J2EE-Frameworks. Einige der Frameworks, die die Java-Reflexion verwenden, sind:
- JUnit – verwendet Reflexion, um die @Test-Annotation zu analysieren, um die Testmethoden zu erhalten und sie dann aufzurufen.
- Spring – Dependency Injection, mehr dazu unter Spring Dependency Injection
- Tomcat Webcontainer leitet die Anfrage an das richtige Modul weiter, indem es deren web.xml-Dateien und Anforderungs-URI analysiert.
- Eclipse automatische Vervollständigung von Methodennamen
- Struts
- Hibernate
Die Liste ist endlos und sie alle verwenden Java-Reflexion, weil all diese Frameworks keine Kenntnis und keinen Zugriff auf benutzerdefinierte Klassen, Schnittstellen, deren Methoden usw. haben. Wir sollten Reflexion nicht in der normalen Programmierung verwenden, wenn wir bereits Zugriff auf die Klassen und Schnittstellen haben, da dies folgende Nachteile hat.
- Schlechte Leistung – Da Java-Reflexion die Typen dynamisch auflöst, ist sie mit Verarbeitungsvorgängen wie dem Scannen des Klassenpfads zur Suche nach der zu ladenden Klasse verbunden, was zu einer langsamen Leistung führt.
- Sicherheitsbeschränkungen – Reflexion erfordert Laufzeitberechtigungen, die für ein unter Sicherheitsmanager laufendes System möglicherweise nicht verfügbar sind. Dies kann dazu führen, dass Ihre Anwendung zur Laufzeit aufgrund des Sicherheitsmanagers fehlschlägt.
- Sicherheitsprobleme – Durch die Verwendung von Reflexion können wir auf Teile des Codes zugreifen, auf die wir nicht zugreifen sollen. Beispielsweise können wir private Felder einer Klasse zugreifen und ihren Wert ändern. Dies kann eine ernsthafte Sicherheitsbedrohung darstellen und dazu führen, dass Ihre Anwendung abnormal reagiert.
- Hoher Wartungsaufwand – Reflexionscode ist schwer zu verstehen und zu debuggen, außerdem können Probleme mit dem Code nicht zur Kompilierzeit gefunden werden, da die Klassen möglicherweise nicht verfügbar sind, was ihn weniger flexibel und schwerer zu pflegen macht.
In Java ist jedes Objekt entweder ein primitiver Typ oder eine Referenz. Alle Klassen, Enums und Arrays sind Referenztypen und erben von java.lang.Object
. Primitive Typen sind – boolean, byte, short, int, long, char, float und double. java.lang.Class ist der Einstiegspunkt für alle Reflexionsoperationen. Für jeden Objekttyp instanziiert die JVM eine unveränderliche Instanz von java.lang.Class
, die Methoden bereitstellt, um die Laufzeiteigenschaften des Objekts zu untersuchen und neue Objekte zu erstellen, seine Methoden aufzurufen und Objektfelder zu erhalten/setzen. In diesem Abschnitt werden wichtige Methoden der Klasse betrachtet. Zur Vereinfachung erstelle ich einige Klassen und Interfaces mit Vererbung Hierarchie.
package com.journaldev.reflection;
public interface BaseInterface {
public int interfaceInt=0;
void method1();
int method2(String str);
}
package com.journaldev.reflection;
public class BaseClass {
public int baseInt;
private static void method3(){
System.out.println("Method3");
}
public int method4(){
System.out.println("Method4");
return 0;
}
public static int method5(){
System.out.println("Method5");
return 0;
}
void method6(){
System.out.println("Method6");
}
// innere öffentliche Klasse
public class BaseClassInnerClass{}
//Mitglieds öffentlicher Aufzählungstyp
public enum BaseClassMemberEnum{}
}
package com.journaldev.reflection;
@Deprecated
public class ConcreteClass extends BaseClass implements BaseInterface {
public int publicInt;
private String privateString="private string";
protected boolean protectedBoolean;
Object defaultObject;
public ConcreteClass(int i){
this.publicInt=i;
}
@Override
public void method1() {
System.out.println("Method1 impl.");
}
@Override
public int method2(String str) {
System.out.println("Method2 impl.");
return 0;
}
@Override
public int method4(){
System.out.println("Method4 overriden.");
return 0;
}
public int method5(int i){
System.out.println("Method4 overriden.");
return 0;
}
// innere Klassen
public class ConcreteClassPublicClass{}
private class ConcreteClassPrivateClass{}
protected class ConcreteClassProtectedClass{}
class ConcreteClassDefaultClass{}
//Mitgliedsaufzählung
enum ConcreteClassDefaultEnum{}
public enum ConcreteClassPublicEnum{}
//Mitgliedsschnittstelle
public interface ConcreteClassPublicInterface{}
}
Lassen Sie uns einige wichtige Reflexionsmethoden für Klassen betrachten.
Holen Sie Klassenobjekt
Wir können die Klasse eines Objekts auf drei Arten erhalten – über die statische Variable class
, die getClass()
-Methode des Objekts und java.lang.Class.forName(String fullyClassifiedClassName)
. Für primitive Typen und Arrays können wir die statische Variable class
verwenden. Wrapper-Klassen bieten eine weitere statische Variable TYPE
, um die Klasse zu erhalten.
// Klasse mithilfe von Reflexion erhalten
Class > concreteClass = ConcreteClass.class;
concreteClass = new ConcreteClass(5).getClass();
try {
// Die folgende Methode wird in Frameworks wie JUnit am häufigsten verwendet
// Spring-Abhängigkeitsinjektion, Tomcat-Webcontainer
// Eclipse-Autovervollständigung von Methodennamen, Hibernate, Struts2 usw.
// Weil ConcreteClass zur Kompilierzeit nicht verfügbar ist
concreteClass = Class.forName("com.journaldev.reflection.ConcreteClass");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(concreteClass.getCanonicalName()); // prints com.journaldev.reflection.ConcreteClass
// für primitive Typen, Wrapper-Klassen und Arrays
Class > booleanClass = boolean.class;
System.out.println(booleanClass.getCanonicalName()); // prints boolean
Class > cDouble = Double.TYPE;
System.out.println(cDouble.getCanonicalName()); // prints double
Class > cDoubleArray = Class.forName("[D");
System.out.println(cDoubleArray.getCanonicalName()); //prints double[]
Class > twoDStringArray = String[][].class;
System.out.println(twoDStringArray.getCanonicalName()); // prints java.lang.String[][]
getCanonicalName()
gibt den kanonischen Namen der zugrunde liegenden Klasse zurück. Beachten Sie, dass java.lang.Class Generics verwendet. Es hilft Frameworks sicherzustellen, dass die abgerufene Klasse eine Unterklasse der Basisklasse des Frameworks ist. Schauen Sie sich das Java Generics Tutorial an, um mehr über Generics und deren Wildcards zu erfahren.
Holen Sie sich die Superklasse
getSuperclass()-Methode auf einem Class-Objekt gibt die Superklasse der Klasse zurück. Wenn diese Klasse entweder die Object-Klasse, ein Interface, ein primitiver Typ oder void repräsentiert, wird null zurückgegeben. Wenn dieses Objekt eine Array-Klasse darstellt, wird das Class-Objekt, das die Object-Klasse repräsentiert, zurückgegeben.
Class<?> superClass = Class.forName("com.journaldev.reflection.ConcreteClass").getSuperclass();
System.out.println(superClass); // prints "class com.journaldev.reflection.BaseClass"
System.out.println(Object.class.getSuperclass()); // prints "null"
System.out.println(String[][].class.getSuperclass());// prints "class java.lang.Object"
Holen Sie sich öffentliche Member-Klassen
Die Methode getClasses()
einer Klassenrepräsentation eines Objekts gibt ein Array zurück, das Klassenobjekte enthält, die alle öffentlichen Klassen, Schnittstellen und Enums repräsentieren, die Mitglieder der von diesem Klassenobjekt dargestellten Klasse sind. Dies umfasst öffentliche Klassen- und Schnittstellenmember, die von Superklassen geerbt wurden, sowie öffentliche Klassen- und Schnittstellenmember, die von der Klasse deklariert wurden. Diese Methode gibt ein Array der Länge 0 zurück, wenn dieses Klassenobjekt keine öffentlichen Klassen- oder Schnittstellenmember hat oder wenn dieses Klassenobjekt einen primitiven Typ, eine Array-Klasse oder void repräsentiert.
Class >[] classes = concreteClass.getClasses();
//[class com.journaldev.reflection.ConcreteClass$ConcreteClassPublicClass,
//class com.journaldev.reflection.ConcreteClass$ConcreteClassPublicEnum,
//interface com.journaldev.reflection.ConcreteClass$ConcreteClassPublicInterface,
//class com.journaldev.reflection.BaseClass$BaseClassInnerClass,
//class com.journaldev.reflection.BaseClass$BaseClassMemberEnum]
System.out.println(Arrays.toString(classes));
Abrufen von Deklarierten Klassen
getDeclaredClasses()
Methode gibt ein Array von Klassenobjekten zurück, die alle als Mitglieder der Klasse deklarierten Klassen und Schnittstellen reflektieren, die durch dieses Klassenobjekt repräsentiert werden. Das zurückgegebene Array enthält keine in vererbten Klassen und Schnittstellen deklarierten Klassen.
//Alle Klassen, Schnittstellen und Enums, die explizit in ConcreteClass
Class >[] explicitClasses = Class.forName("com.journaldev.reflection.ConcreteClass").getDeclaredClasses();
deklariert sind, abrufen//druckt [Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassDefaultClass,
//Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassDefaultEnum,
//Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassPrivateClass,
//Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassProtectedClass,
//Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassPublicClass,
//Klasse com.journaldev.reflection.ConcreteClass$ConcreteClassPublicEnum,
//Schnittstelle com.journaldev.reflection.ConcreteClass$ConcreteClassPublicInterface]
System.out.println(Arrays.toString(explicitClasses));
Den deklarierenden Klassenabrufen
getDeclaringClass()
-Methode gibt das Klassenobjekt zurück, das die Klasse darstellt, in der sie deklariert wurde.
Class > innerClass = Class.forName("com.journaldev.reflection.ConcreteClass$ConcreteClassDefaultClass");
//druckt com.journaldev.reflection.ConcreteClass
System.out.println(innerClass.getDeclaringClass().getCanonicalName());
System.out.println(innerClass.getEnclosingClass().getCanonicalName());
Paketnamen abrufen
getPackage()
-Methode gibt das Paket für diese Klasse zurück. Der Klassenlader dieser Klasse wird verwendet, um das Paket zu finden. Wir können die getName()
-Methode von Package aufrufen, um den Namen des Pakets zu erhalten.
//prints "com.journaldev.reflection"
System.out.println(Class.forName("com.journaldev.reflection.BaseInterface").getPackage().getName());
Klassenmodifier abrufen
getModifiers()
-Methode gibt die int-Repräsentation der Klassenmodifier zurück. Wir können die Methode java.lang.reflect.Modifier.toString()
verwenden, um sie im Zeichenkettenformat zu erhalten, wie es im Quellcode verwendet wird.
System.out.println(Modifier.toString(concreteClass.getModifiers())); //prints "public"
//prints "public abstract interface"
System.out.println(Modifier.toString(Class.forName("com.journaldev.reflection.BaseInterface").getModifiers()));
Typparameter abrufen
getTypeParameters()
gibt das Array von TypeVariable zurück, wenn der Klasse Typparameter zugeordnet sind. Die Typparameter werden in der gleichen Reihenfolge zurückgegeben wie sie deklariert wurden.
//Typparameter abrufen (Generics)
TypeVariable >[] typeParameters = Class.forName("java.util.HashMap").getTypeParameters();
for(TypeVariable > t : typeParameters)
System.out.print(t.getName()+",");
Implementierte Schnittstellen abrufen
getGenericInterfaces()
-Methode gibt das Array der von der Klasse implementierten Schnittstellen mit generischen Typinformationen zurück. Wir können auch getInterfaces()
verwenden, um die Klassenrepräsentation aller implementierten Schnittstellen zu erhalten.
Type[] interfaces = Class.forName("java.util.HashMap").getGenericInterfaces();
//prints "[java.util.Map, interface java.lang.Cloneable, interface java.io.Serializable]"
System.out.println(Arrays.toString(interfaces));
//prints "[interface java.util.Map, interface java.lang.Cloneable, interface java.io.Serializable]"
System.out.println(Arrays.toString(Class.forName("java.util.HashMap").getInterfaces()));
Alle öffentlichen Methoden abrufen
getMethods()
-Methode gibt das Array der öffentlichen Methoden der Klasse zurück, einschließlich der öffentlichen Methoden ihrer Superklassen und Superinterfaces.
Method[] publicMethods = Class.forName("com.journaldev.reflection.ConcreteClass").getMethods();
//prints öffentliche Methoden von ConcreteClass, BaseClass, Object
System.out.println(Arrays.toString(publicMethods));
Alle öffentlichen Konstruktoren abrufen
getConstructors()
-Methode gibt die Liste der öffentlichen Konstruktoren der Klassenreferenz des Objekts zurück.
//Get All public constructors
Constructor >[] publicConstructors = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructors();
//prints öffentliche Konstruktoren von ConcreteClass
System.out.println(Arrays.toString(publicConstructors));
Alle öffentlichen Felder abrufen
getFields()
-Methode gibt das Array der öffentlichen Felder der Klasse zurück, einschließlich der öffentlichen Felder ihrer Superklassen und Superinterfaces.
// Alle öffentlichen Felder abrufen
Field[] publicFields = Class.forName("com.journaldev.reflection.ConcreteClass").getFields();
// Gibt öffentliche Felder von ConcreteClass, seiner Superklasse und seiner Superinterfaces aus
System.out.println(Arrays.toString(publicFields));
Alle Annotationen abrufen
getAnnotations()
-Methode gibt alle Annotationen für das Element zurück. Wir können es mit Klassen, Feldern und Methoden verwenden. Beachten Sie, dass nur Annotationen mit der Retention-Politik RUNTIME über Reflection verfügbar sind. Siehe Java-Annotations-Tutorial. Wir werden dies in späteren Abschnitten genauer betrachten.
java.lang.annotation.Annotation[] annotations = Class.forName("com.journaldev.reflection.ConcreteClass").getAnnotations();
// Gibt aus [@java.lang.Deprecated()]
System.out.println(Arrays.toString(annotations));
Die Reflection-API bietet mehrere Methoden zum Analysieren von Klassenfeldern und zum Ändern ihrer Werte zur Laufzeit. In diesem Abschnitt werden einige der häufig verwendeten Reflektionsfunktionen für Methoden betrachtet.
Öffentliches Feld erhalten
Im letzten Abschnitt haben wir gesehen, wie Sie die Liste aller öffentlichen Felder einer Klasse erhalten können. Die Reflection-API bietet auch eine Methode zum Abrufen eines bestimmten öffentlichen Felds einer Klasse durch die getField()
-Methode. Diese Methode sucht nach dem Feld im angegebenen Klassenverweis, dann in den Superinterfaces und anschließend in den Superklassen.
Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("interfaceInt");
Der oben genannte Aufruf gibt das Feld von der BaseInterface zurück, das von der ConcreteClass implementiert wird. Wenn kein Feld gefunden wird, wird eine NoSuchFieldException ausgelöst.
Feld deklarierende Klasse
Mit getDeclaringClass()
des Feldobjekts können wir die Klasse abrufen, die das Feld deklariert.
try {
Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("interfaceInt");
Class<?> fieldClass = field.getDeclaringClass();
System.out.println(fieldClass.getCanonicalName()); //prints com.journaldev.reflection.BaseInterface
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
Feldtyp abrufen
Die Methode getType()
gibt das Klassenobjekt für den deklarierten Feldtyp zurück. Wenn das Feld ein primitiver Typ ist, gibt es das Wrapper-Klassenobjekt zurück.
Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("publicInt");
Class<?> fieldType = field.getType();
System.out.println(fieldType.getCanonicalName()); //prints int
Get/Set öffentlichen Feldwert
Wir können den Wert eines Feldes in einem Objekt mithilfe von Reflexion erhalten und setzen.
Field field = Class.forName("com.journaldev.reflection.ConcreteClass").getField("publicInt");
ConcreteClass obj = new ConcreteClass(5);
System.out.println(field.get(obj)); //prints 5
field.setInt(obj, 10); //setting field value to 10 in object
System.out.println(field.get(obj)); //prints 10
Die get()-Methode gibt ein Objekt zurück. Wenn das Feld ein primitiver Typ ist, gibt es den entsprechenden Wrapper-Klasse zurück. Wenn das Feld statisch ist, können wir null als Objekt in die get()-Methode übergeben. Es gibt mehrere set*()-Methoden, um ein Objekt auf das Feld zu setzen oder verschiedene Arten von primitiven Typen auf das Feld zu setzen. Wir können den Typ des Feldes abrufen und dann die richtige Funktion aufrufen, um den Feldwert korrekt zu setzen. Wenn das Feld final ist, werfen die set()-Methoden java.lang.IllegalAccessException.
Get/Set privaten Feldwert
Wir wissen, dass private Felder und Methoden außerhalb der Klasse nicht zugänglich sind, aber mithilfe von Reflexion können wir den privaten Feldwert erhalten/setzen, indem wir die Java-Zugriffsüberprüfung für Feldmodifikatoren deaktivieren.
Field privateField = Class.forName("com.journaldev.reflection.ConcreteClass").getDeclaredField("privateString");
// Zugriffsüberprüfung deaktivieren mit dem folgenden Methodenaufruf
privateField.setAccessible(true);
ConcreteClass objTest = new ConcreteClass(1);
System.out.println(privateField.get(objTest)); // prints "private string"
privateField.set(objTest, "private string updated");
System.out.println(privateField.get(objTest)); //prints "private string updated"
Unter Verwendung der Reflexion können wir Informationen über eine Methode abrufen und sie auch aufrufen. In diesem Abschnitt werden verschiedene Möglichkeiten erläutert, eine Methode abzurufen und auf private Methoden zuzugreifen.
Öffentliche Methode abrufen
Mit getMethod() können wir eine öffentliche Methode einer Klasse abrufen. Wir müssen den Methodennamen und die Parametertypen der Methode übergeben. Wenn die Methode in der Klasse nicht gefunden wird, sucht die Reflexions-API nach der Methode in der Superklasse. Im folgenden Beispiel rufe ich die put()-Methode von HashMap über Reflexion auf. Das Beispiel zeigt auch, wie die Parametertypen, Methodenmodifier und der Rückgabetyp einer Methode abgerufen werden können.
Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
// Parametertypen der Methode abrufen, gibt "[class java.lang.Object, class java.lang.Object]" aus
System.out.println(Arrays.toString(method.getParameterTypes()));
// Rückgabetyp der Methode abrufen, gibt "class java.lang.Object" zurück, Klassenreferenz für void
System.out.println(method.getReturnType());
// Methodenmodifier abrufen
System.out.println(Modifier.toString(method.getModifiers())); //prints "public"
Aufrufen der öffentlichen Methode
Wir können die invoke() Methode des Method-Objekts verwenden, um eine Methode aufzurufen. Im unten stehenden Beispiel rufe ich die put-Methode auf HashMap über Reflexion auf.
Method method = Class.forName("java.util.HashMap").getMethod("put", Object.class, Object.class);
Map<String, String> hm = new HashMap<>();
method.invoke(hm, "key", "value");
System.out.println(hm); // prints {key=value}
Wenn die Methode statisch ist, können wir NULL als Objektargument übergeben.
Aufrufen privater Methoden
Wir können getDeclaredMethod() verwenden, um die private Methode zu erhalten, und dann die Zugrüfprüfung ausschalten, um sie aufzurufen. Das unten stehende Beispiel zeigt, wie wir die Methode3() der Basisklasse aufrufen können, die statisch ist und keine Parameter hat.
// Aufrufen privater Methode
Method method = Class.forName("com.journaldev.reflection.BaseClass").getDeclaredMethod("method3", null);
method.setAccessible(true);
method.invoke(null, null); //prints "Method3"
Die Reflection API bietet Methoden zum Abrufen der Konstruktoren einer Klasse zur Analyse und wir können neue Instanzen der Klasse erstellen, indem wir den Konstruktor aufrufen. Wir haben bereits gelernt, wie man alle öffentlichen Konstruktoren erhält.
Öffentlichen Konstruktor abrufen
Wir können die Methode `getConstructor()` auf der Klassenrepräsentation des Objekts verwenden, um einen bestimmten öffentlichen Konstruktor zu erhalten. Das folgende Beispiel zeigt, wie man den Konstruktor der oben definierten ConcreteClass und den Konstruktor ohne Argumente von HashMap erhält. Es zeigt auch, wie man das Array der Parameterarten für den Konstruktor erhält.
Constructor > constructor = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructor(int.class);
// Konstruktorparameter erhalten
System.out.println(Arrays.toString(constructor.getParameterTypes())); // prints "[int]"
Constructor > hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes())); // prints "[]"
Objekt mit Konstruktor instanziieren
Wir können die Methode `newInstance()` auf dem Konstruktorobjekt verwenden, um eine neue Instanz der Klasse zu instanziieren. Da wir Reflexion verwenden, wenn wir die Klasseninformationen zur Compile-Zeit nicht haben, können wir sie einem Objekt zuweisen und dann Reflexion verwenden, um auf ihre Felder zuzugreifen und ihre Methoden aufzurufen.
Constructor > constructor = Class.forName("com.journaldev.reflection.ConcreteClass").getConstructor(int.class);
// Konstruktorparameter erhalten
System.out.println(Arrays.toString(constructor.getParameterTypes())); // prints "[int]"
Object myObj = constructor.newInstance(10);
Method myObjMethod = myObj.getClass().getMethod("method1", null);
myObjMethod.invoke(myObj, null); //prints "Method1 impl."
Constructor > hashMapConstructor = Class.forName("java.util.HashMap").getConstructor(null);
System.out.println(Arrays.toString(hashMapConstructor.getParameterTypes())); // prints "[]"
HashMap myMap = (HashMap) hashMapConstructor.newInstance(null);
Annotationen wurden in Java 1.5 eingeführt, um Metadateninformationen über die Klasse, Methoden oder Felder bereitzustellen und werden jetzt intensiv in Frameworks wie Spring und Hibernate verwendet. Die Reflection-API wurde ebenfalls erweitert, um Unterstützung für die Analyse von Annotationen zur Laufzeit bereitzustellen. Mit der Reflection-API können wir Annotationen analysieren, deren Retentionsrichtlinie Runtime ist. Ich habe bereits ein ausführliches Tutorial zu Annotationen und wie wir die Reflection-API zum Parsen von Annotationen verwenden können, geschrieben. Daher würde ich Ihnen empfehlen, sich das Java Annotations Tutorial anzusehen. Das ist alles für das Beispiel-Tutorial zur Java-Reflexion. Ich hoffe, Ihnen hat das Tutorial gefallen, und Sie haben die Bedeutung der Java Reflection-API verstanden.
Source:
https://www.digitalocean.com/community/tutorials/java-reflection-example-tutorial