Mit Java können wir nicht nur verschiedene Informationen über das Erhalten von Klassen während der Zusammenstellung des Zusammenstellungszeitraums erhalten, sondern ermöglicht es uns auch, während der Laufzeit durch Reflexion verschiedene Informationen über Klassen zu erhalten. Abrufen von Klasseninformationen durch Reflexion und nach dem Erhalt von Klasseninformationen können Sie den folgenden verwandten Inhalt erhalten:
In diesem Artikel wird auch die Java -Reflexion aus den oben genannten Aspekten eingeführt. Alle in diesem Artikel beteiligten Codes werden reflektiert
Erstens wird eine Java -Klasse als Reflexionsobjekt veröffentlicht. Der Inhalt der Klasse lautet wie folgt:
public abstract class fatherObject implements runnable {public void dosomething () {system.out.println ("Do Things ..."); }} public class BeispielObject erweitert fatherObject {public int age = 30; public String name = "byhieg"; Private Ganzzahl Score = 60; public void printName () {System.out.println (Name); } public int getage () {return ay; } public void setage (int age) {this.age = älter; } public String getName () {return name; } public void setName (String -Name) {this.name = name; } public Integer getCore () {return Score; } public void setScore (Integer Score) {this.score = Score; } public BeispielObject () {} public BeispielObject (String -Name) {} public BeispielObject (int age, Integer Score) {} @Override public void dosomething () {Super.dosomething (); } @Override public void run () {System.out.println ("run ..."); }}Klassenobjekt
Unsere Anwendung wird den Wissenspunkt der Reflexion verwenden. Wir müssen die Informationen der Klasse zur Laufzeit erhalten und einige spezifische Vorgänge ausführen, die auf den Informationen der Klasse basieren. Das erste ist, die Informationen der Klasse zu erhalten, und ein Klassenobjekt wird im JDK bereitgestellt, um die Informationen der Klasse zu speichern. Daher besteht der erste Schritt in der Reflexion darin, das Klassenobjekt zu erhalten. Es gibt zwei Möglichkeiten, Klassenobjekte in JDK zu erhalten.
Das erste ist, dass Sie das Klassenobjekt auf folgende Weise direkt erhalten können, wenn Sie den Namen der Klasse beim Schreiben von Code kennen:
Class exampleObjectClass = ExampleObject.class;
Der zweite Typ ist, dass Sie, wenn Sie den Namen der Klasse beim Schreiben des Codes, aber zur Laufzeit, nicht kennen, eine Zeichenfolge des Klassennamens erhalten und das Klassenobjekt auf folgende Weise erhalten können:
Class exampleObjectClass = Class.forName("cn.byhieg.reflectiontutorial.ExampleObject");
Beachten Sie, dass diese Methode 2 Bedingungen haben muss. Erstens muss die Zeichenfolge in Forname vollständig qualifiziert sein, und zweitens muss die Klassenklasse unter dem Pfad des Klassenpfads liegen, da die Methode eine Ausnahme von ClassNotFoundException macht.
Nachdem Sie dieses Klassenobjekt erhalten haben, können Sie verschiedene Informationen über die Klasse erhalten. Einige Informationen wurden am Anfang erwähnt. Lassen Sie uns im Folgenden über die Informationen über die nicht erwähnte Klasse sprechen.
Holen Sie sich den Namen der Klasse
Es gibt zwei Möglichkeiten, den Namen der Klasse zu erhalten, eines ist GetName () und der andere ist GetImlenname (). Der erste erhält einen voll qualifizierten Namen, und der zweite erhält einen Namen dieser Klasse ohne Paketnamen. Schauen Sie sich das folgende Beispiel an: Klassenobjekt, das über den obigen Code erhalten wurde.
String fullClassName = exampleObjectClass.getName (); String SimpleClassName = BeispielObjectClass.getSimpename (); System.out.println (FullClassName); System.out.println (simimalClassName); System.out.println (simimalClassName);
Die Ergebnisse sind wie folgt:
Cn.ByHieg.ReflectionTutorial.ExampleObjectExampleAbject
Holen Sie sich den Paketnamen der Klasse, die übergeordnete Klasse und die Implementierungsschnittstelle
Der Paketname und die übergeordnete Klasse der Klasse können über den folgenden Code erhalten werden.
// Paketinformationspaket apackage = BeispielObjectClass.getPackage (); System.out.println (Apackage); // Elternklassenklasse SuperClass = exampledjectClass.getSuperClass () erhalten; System.out.println (SuperClass.getSimplename ());
Die Ergebnisse sind wie folgt:
Paket cn.ByHieg.ReflectionTutorialFatherObject
Offensichtlich ist es auch ein Klassenobjekt, den Rückgabewert der übergeordneten Klasse zu erhalten. Anschließend können Sie dieses Objekt verwenden, um Informationen über die übergeordnete Klasse zu erhalten, z. B. zu beurteilen, ob die Elternklasse eine abstrakte Klasse ist.
System.out.println("父类是不是抽象类" + Modifier.isAbstract(superClass.getModifiers()));
GetModifiers können Klassenmodifikatoren erhalten und so Klassenmodifikatoren erhalten. Natürlich kann diese GetModifiers nicht nur als Klassenobjekte bezeichnet werden, sondern Methodenobjekte können aufgerufen werden.
Sie können die Methode in der Klasse java.lang.reflect.modifier verwenden, um den Typ des Modifikators zu überprüfen:
Modifikator.isabstract (int modificer); modifikator.isfinal (int modifikators); modifikator Modifikatoren); modifier.isstrict (int modificer); modifier.ISSynchronized (int modificer); modifier.Istansient (int modifikators); modifier.isvolatile (int -Modifikatoren);
Darüber hinaus können wir auch die von der übergeordnete Klasse implementierte Schnittstelle implementieren lassen
// Die Schnittstellenklasse [] classes = superclass.getInterfaces () erhalten; System.out.println ("Schnittstellen der Elternklasse" + Klassen [0]);Da Java -Klassen viele Schnittstellen implementieren können, verwenden sie Arrays. Wenn Sie sie jedoch tatsächlich verwenden, müssen Sie zuerst die Länge des Arrays bestimmen.
Im Folgenden werden wir uns darauf konzentrieren, den oben aufgelisteten Inhalt zu erklären.
Konstruktor
Mit Java Reflection können Sie einen Klassenkonstruktor abrufen und ein Objekt zur Laufzeit dynamisch basierend auf dem Konstruktor erstellen. Erstens erhält Java eine Instanz des Konstruktors durch:
// ConstructorConstructor [] constructors = exampledjectClass.getConstructors (); für (Konstruktorkonstruktor: Konstruktoren) {System.out.println (constructor.toString ()); }Die Ergebnisse sind wie folgt:
public cn.byhieg.reflectiontutororial.exampleObject (int, java.lang.Ineger) öffentlich cn.byhieg.reflectiontutorial
Wenn Sie den Parametertyp des Konstruktors im Voraus kennen, können Sie die folgende Methode verwenden, um den angegebenen Konstruktor wie folgt zu erhalten:
Constructor constructor = exampleObjectClass.getConstructor (string.class); System.out.println (Constructor.toString ());
Das Ergebnis ist offensichtlich:
public cn.byhieg.reflectiontutorial.ExampleObject(java.lang.String)
Ein anderer Konstruktor kann ebenfalls auf folgende Weise erhalten werden
Constructor constructor = exampleObjectClass.getConstructor (int.Class, Integer.class); System.out.println (Constructor.toString ());
Wenn wir die Konstruktorparameter nicht kennen und nur alle Konstruktorobjekte erhalten können, können wir die Parameter erhalten, die jeder Konstruktor wie folgt verwendet:
Constructor [] constructors = BeispielObjectClass.getConstructors (); für (Konstruktorkonstruktor: Konstruktoren) {class [] parameterTypes = constructor.getParameterTypes (); System.out.println ("Konstruktorparameter sind als folgt ====================================================================================================================================================================================================================================================================================================== ========================================================================== für (Klasse clz: parameterTypes) {System.out.println ("parameterType" + clz.toString ());Die Ergebnisse sind wie folgt:
Die Konstruktorparameter sind wie folgt.
Hier ist ersichtlich, dass die parameterlose Konstruktionsmethode das Ergebnis nicht druckt. Das Klassenobjekt des Grundtyps und das Klassenobjekt des Referenztyps sind unterschiedlich.
Jetzt kann ein Objekt dynamisch basierend auf verschiedenen Informationen des Konstruktors erstellt werden.
Object Object = Constructor.NewinStance (1.100); System.out.println (Object.ToString ());
Es gibt zwei Bedingungen für das Erstellen eines Objekts. Der erste wird über einen Parameterkonstruktor erstellt. Die zweite ist, dass das Konstruktorobjekt über den GetConstructor erhalten werden muss, der die Parameterinformationen übergibt.
Die erste Bedingung ist, dass für Objekte, die ohne Parameterkonstruktionsmethoden erstellt werden können, nicht erforderlich sind, um das Konstruktorobjekt zu erhalten. Das Klassenobjekt ruft die Methode von NewInstance () auf und erstellt das Objekt direkt.
Die zweite Bedingung ist, dass das Konstruktorobjekt über das Formular examplejectClass.getConstructor (String.Class) erhalten werden muss. Es wäre falsch, das Konstruktor -Array durch GetConstructors zu erhalten und dann das angegebene Konstruktorobjekt aufzurufen, um das Objekt in JDK1.8 zu erstellen. Aber JDK1.6 ist normal.
Variable
Mit Java Reflection können Sie zur Laufzeit variable Informationen einer Klasse erhalten und ein Objekt erstellen und seinen variablen Wert gemäß der obigen Methode festlegen. Erstens werden alle öffentlichen Variablen erhalten, indem die folgende Methode folgt:
Field [] fields = exampleObjectClass.getFields (); für (Feldfeld: Felder) {System.out.println ("Variable ist:" + field.toString ()); }Die Ergebnisse sind wie folgt:
Die Variable lautet: public int cn.byhieg.reflectiontutorial
Offensichtlich sind alle erhaltenen öffentlichen Variablen öffentlich, und der obige private variable Punktzahl wird nicht erhalten.
So wie der Konstruktor erhalten wird, können wir einen Parameternamen angeben und dann die angegebene Variable abrufen:
Field Field = BeispielObjectClass.getField ("Alter"); System.out.println ("Variable ist:" + field.toString ());Der Name der TOString -Methode der obigen Variablen ist zu lang. Java bietet die GetName -Methode für die Feldklasse, die den Namen der in der Klasse geschriebenen Variablen zurückgibt. Der obige Code kann in field.getName () geändert werden.
Reflexion bietet nicht nur eine Möglichkeit, Variablen zu erhalten, sondern auch eine Möglichkeit, Variablenwerte festzulegen. Durch die folgende Methode können Sie den variablen Wert einer dynamisch generierten Klasse ändern:
BeispielObject Object = ((BeispielObject) Constructor1.Newinstance ("byhieg")); System.out.println ("Das ursprüngliche Alter ist" + Objekt.age); field.set (Objekt, 10); System.out.println ("Das Alter nach der Änderung ist" + Objekt.age);Die Ergebnisse sind wie folgt:
Das ursprüngliche Alter beträgt 30 und das Alter nach der Änderung 10
Gemäß dem obigen Code können Sie ein Feldobjekt mit dem Namen Age abrufen, dann die festgelegte Methode des Objekts aufrufen, ein Objekt und den zu ändernden Wert übergeben und dann den Wert des Objekts ändern. Beachten Sie, dass diese Methode nicht nur für Mitgliedsvariablen nützlich ist, sondern auch für statische Variablen. Wenn es sich um eine statische Variable handelt, ist es natürlich in Ordnung, Null zu übergeben, ohne das Objekt zu übergeben.
Verfahren
Java Reflection liefert uns nicht nur mit variablen Informationen zur Klasse. Durch die Reflexion können wir Methodenname, Methodenparameter, Methodenrückgabeart und Aufrufmethoden erhalten.
Holen Sie sich zunächst die Methode über den folgenden Code:
// die öffentliche Methode der Ausgabemethode [] methods = exampledjectClass.getMethods (); für (Methode Methode: Methoden) {System.out.println ("method ="+ method.getName ()); }Code, der bekannt aussieht, als würde man Variablen bekommen. GetName wird hier direkt aufgerufen, um den in der Klasse geschriebenen Methodennamen zu erstellen. Nachdem Sie dies geschrieben haben, sollten Sie natürlich denken, dass Java auch spezifische Methoden basierend auf Parametern bereitstellt.
Methodenmethode = BeispielObjectClass.getMethod ("Setage", int.Class); System.out.println (method.getName ());Der Unterschied besteht darin, dass die GetMethod -Methode auch die Parametertypinformationen übergeben muss, und das Nachdenken bietet eine Methode, um Methodenparameter und Rückgabetyp zu erhalten. Beispiele für das Erhalten von Methodenparametern sind wie folgt:
Methodenmethode = BeispielObjectClass.getMethod ("Setage", int.Class); System.out.println (method.getName ()); für (Klasse clz: method.getParameterTypes ()) {System.out.println ("Parameter der Methode" + clz.getName ()); }Die Ergebnisse sind wie folgt:
Der Parameter int der Setage -Methode
Ein Beispiel für den Erhalt des Methodenrückgabearts ist wie folgt:
System.out.println(method.getReturnType().getName());
Die Ergebnisse sind wie folgt:
void
Darüber hinaus unterstützt Java Reflection Methoden, die durch Aufrufanrufe erhalten wurden. Beispiele sind wie folgt:
method.invoke(exampleObjectClass.newInstance(),1);
Der erste Parameter aufgerufen ist dieses Objekt, und der zweite Parameter ist ein Array mit variabler Länge, und die Parameter der Methode werden übergeben. Wie Feldobjekte für statische Methoden können Sie Nullübergeben und aufrufen statische Methoden übergeben.
Private Variablen und private Methoden
Die obige Methode kann nur öffentliche Methoden und Variablen erhalten, können jedoch keine nicht öffentlichen modifizierten Methoden und Variablen erhalten. Java bietet zusätzliche Methoden, um nicht öffentliche Variablen und Methoden zu erhalten. Das heißt, private Variablen und Methoden werden durch GetDeclaredfields und GetDeclaredMethods -Methoden erhalten. Es unterstützt auch die Verwendung von GetDeclaredField (Variablenname) und getDeclaredMethod (Methodenname), um den angegebenen Variablennamen und den methodischen Namen zu erhalten. Die auf diese Weise erhaltenen Feldobjekte und Methodenobjekte können jedoch nicht direkt verwendet werden. Diese Objekte müssen für den normalen Gebrauch SetAccessible (TRUE) bezeichnet werden. Die folgende Methode kann die gleiche sein, wie oben erwähnt.
Anmerkung
Schreiben Sie zuerst eine Klasse mit Anmerkungen:
@Myannotation (name = "byhieg", value = "hello wort") public class AnnotationObject {@myannotation (name = "field", value = "variable") public String Feld; @Myannotation (name = "methode", value = "methode") public void doSomething () {System.out.println ("mach etwas"); } public void dootherthing (@myannotation (name = "param", value = "param") String Param) {}}@retention (retentionPolicy.Runtime) public @Interface Myannotation {public String name (); public String value ();}Java liefert uns Informationen über das Erhalten von Klassenanmerkungen zur Laufzeit, und wir können Klassenanmerkungen, Methodenanmerkungen, Parameteranmerkungen und variable Anmerkungen erhalten.
Wie die obige Erfassungsmethode bietet Java zwei Erfassungsmethoden. Eine davon ist, alle Anmerkungen zu erhalten und ein Array zurückzugeben, und die zweite ist, die angegebenen Anmerkungen anzugeben.
Nehmen wir eine Klassenanmerkmale als Beispiel, um die folgenden zwei Möglichkeiten zu erläutern.
Klasse clz = AnnotationObject.class; Annotation [] Annotationen = clz.getannotations (); Annotation Annotation = clz.getannotation (AnnotationObject.class);
Anschließend kann die anschließende Verarbeitung basierend auf der erhaltenen Annotation durchgeführt werden. Das Folgende ist ein Beispiel für die Verarbeitung:
für (Annotation Annotation: Annotationen) {if (Annotationsinstanz von Myannotation) {Myannotation myannotation = (myannotation) Annotation; System.out.println ("Name:" + myannotation.name ()); System.out.println ("Wert:" + myannotation.Value ()); }}Die obigen Klassenanmerkungen werden erhalten, indem Getannotationen mithilfe von Klassenobjekten aufgerufen werden. Die Methodenanmerkungen und variablen Anmerkungen sind gleich. Ich rufe getDeclaredAnnotations mithilfe von Methodenobjekten bzw. Feldobjekten auf, um Anmerkungen zu erhalten. Ich habe nicht viel zu sagen. Siehe zum Beispiel den Reflexionscode
Parameteranmerkungen sind ein relativ störendes Element. Die Erfassungsmethode wird verglichen. Der erste Schritt besteht darin, zuerst das Methodenobjekt zu erhalten und GetParameterAnnotations aufzurufen. Dieser Rückgabewert ist jedoch ein zweidimensionales Array, da das Methodenobjekt viele Parameter aufweist und jeder Parameter viele Anmerkungen aufweist. Beispiele sind wie folgt:
Methode Methode1 = clz.getMethod ("Dootherthing", String.class); Annotation [] [] AnnotationInparam = methode1.getParameterAnnotations (); Class [] params = methode1.getParameterTypes (); int i = 0; für (Annotation [] Annotationen: AnnotationInparam) {Klasse para = params [i ++]; für (Annotation Annotation: Annotationen) {if (Annotationsinstanz von Myannotation) {Myannotation myannotation = (myannotation) Annotation; System.out.println ("Param:" + para.getName ()); System.out.println ("Name:" + myannotation.name ()); System.out.println ("Wert:" + myannotation.Value ()); }}}Generika
Da Java -Generika durch Lösche implementiert werden, ist es schwierig, Informationen über den spezifischen parametrisierten Generika -Typ direkt zu erhalten. Wir können jedoch generische Informationen über eine indirekte Form unter Verwendung von Reflexion erhalten. Zum Beispiel die folgende Klasse:
public class genericObject {publiclist <string> listen; public list <string> getLists () {return lists; } public void setlists (list <string> lists) {this.lists = lists; }}Wenn eine Methode eine generische Klasse zurückgibt, können wir GetgenericReturnType über das Methodenobjekt aufrufen, um GETGENICRETURNTYPE zu erhalten, um das zu erhalten, was der spezifische Parameterisierungstyp dieser generischen Klasse ist. Schauen Sie sich den folgenden Code an:
Klasse clz = genericObject.class; Methode Methode = clz.getMethod ("getLists"); Type generictype = methode.getgenericReturnType (); if (genericType -Instanz von parameterizedType) {parameterizedType parameterizedType = ((parameterizedtype) genericType); Typ [] Typen = parameterizedtype für (Typ Typ: Typ: Typ) {Klasse tatsächliche clz = ((Klasse) Typ); System.out.println ("Parametrisierungstyp ist:" + tatsächlicheClz); }}Die Ergebnisse sind wie folgt:
参数化类型为: class java.lang.String
Die Schritte sind etwas umständlich, daher lautet die folgende Erklärung:
Ich habe spezifische Informationen über die Generika erhalten, indem ich die Ergebnisse betrachtete.
Wenn keine Methode einen generischen Typ zurückgibt, können wir auch den parametrisierten Typ des generischen Typs nach dem Parameter der Methode als generische Klasse abrufen, z. B. die SetLists -Methode in der obigen Klasse. Beispiele sind wie folgt:
Methode setMethod = clz.getMethod ("setlists", list.class); Type [] genericParameterTypes = setMethod.getGenericParameterTypes (); für (type genericParameterType: genericParameterTypes) {System.out.println ("genericParameterTypes ist:" + genericParameterType.gettTypeName ()); if (genericParameterType -Instanz von parameterizedType) {parameterizedtype parameterizedType = ((parameterizedtype) genericParameterType); System.out.println ("parameterizedType ist:" + parameterizedType.gettTypeName ()); Typtypen [] = parameterizedType.getactualtTypeRgumente (); für (Typ Typ: Typ: Typ) {System.out.println ("parametrisierter Typ ist:" + ((Klasse) Typ) .getName ()); }}}Die Ausführungsergebnisse sind wie folgt:
GenericParameterType sind: java.util.list <java.lang.String> parameterizedType ist: java.util.list <java.lang.String> parametrisierter Typ ist: java.lang.String
Da die Parameter der Methode möglicherweise mehr als einen generischen Typ aufweisen, können wir eine Array erhalten, um festzustellen, ob jedes Element einen parametrisierten Typ hat. Die nachfolgenden Schritte ähneln den oben genannten, daher werde ich nicht viel sagen.
Wenn auch die Methodenparameter keine generischen Klassen enthalten, wird nur der letzte Fall über den variablen Typ, dh die Feldklasse verwendet. Beispiele sind wie folgt:
Field field = clz.getfield ("lists"); Type type = field.getgenericype (); if (Typinstanz von parameterizedType) {parameterizedtype parameterizedType = (((parameterizedtype)); Typ [] Typen = parameterizedtype für (Typtyp1: Typen) {System.out.println ("Parametrisierter Typ:" + ((Klasse) type1) .Getypename ()); }}Das Prinzip ist das gleiche wie oben, außer dass das Typobjekt über das Feld ist. GETGENICTYPE (), sodass ich nicht viel über die verbleibenden Vorgänge sage.
Dies ist die Einführung, um den parametrisierten Generikentyp durch Reflexion zu erhalten.
Array
Java Reflection kann auf einem Array arbeiten, einschließlich des Erstellens eines Arrays, dem Zugriff auf Werte in einem Array und der Erlangung eines Klassenobjekts eines Arrays.
Lassen Sie uns einfach darüber sprechen, ein Array erstellen und auf die Werte im Array zugreifen: Die Verwendung der Array -Klasse in Reflexion ist das unterhalb des reflektierenden Pakets.
// Erstellen Sie ein Array von Int -Typen mit einer Länge von 3 int [] intarrray = (int []) Array.Newinstance (int.Class, 3); // dem Array durch Reflexion für (int i = 0; i <intarrray.length; i ++) {array.set (intarrray, i, i+2) einen Wert zuweisen; } // Array in Form der Reflexion erhalten Sie den Wert im Array für (int i = 0; i <intarrray.length; i ++) {System.out.println (array.get (intarray, i)); }Das obige soll ein Array erstellen und mithilfe der Reflexion auf die Werte im Array zugreifen.
Für Klassenobjekte, die ein Array erhalten, können Sie einfach die int [] Klasse oder Klasse verwenden.
Klasse clz = class.Forname ("[i"); System.out.println (clz.gettTypename ());Das Ergebnis ist:
int[]
Die Zeichenfolge in diesem Forname [ repräsentiert ein Array, ich stelle einen int, float is f , doppelt ist d usw. Wenn Sie ein Array von gewöhnlichen Objekten erhalten möchten, verwenden Sie das folgende Formular:
Class stringClz = Class.forName("[Ljava.lang.String;");
[ Sagen Sie, es ist ein Array, die rechte Seite von L ist der Klassenname, und die rechte Seite vom Typ ist a ; ;
Diese Möglichkeit, das Klassenobjekt des Arrays zu erhalten, ist zu umständlich.
Nach dem Erhalt des Klassenobjekts des Arrays können einige seiner einzigartigen Methoden aufgerufen werden, z. B. das Aufrufen von GetComponentType , um die Typinformationen von Array -Mitgliedern zu erhalten. Beispielsweise ist ein INT -Array ein Mitgliedstyp, der int ist.
System.out.println(clz.getComponentType().getTypeName());
Das Ergebnis ist int
Zusammenfassen
Diesmal enden die verschiedenen Anwendungen der Reflexion damit, und es kann in Zukunft ausführliche Erklärungen für Wissen geben. Für einen bestimmten Code können Sie sich den Reflexionscode ansehen
Im SRC -Paket gibt es verschiedene Klassen, und in der Testklasse ist es Zugriff auf diese Klassen.
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels für das Studium oder die Arbeit eines jeden hilfreich sein wird. Ich hoffe auch, Wulin.com mehr zu unterstützen!