Detaillierte Erklärung der Java -Reflexion
In diesem Artikel werden immer noch kleine Beispiele verwendet, um zu veranschaulichen, da ich immer das Gefühl habe, dass Fallbetrieben das Beste ist. Andernfalls werden Sie nach dem Lesen nicht verstehen, wenn Sie die Theorie nur lesen. Es wird jedoch empfohlen, dass Sie nach dem Lesen des Artikels auf die Theorie zurückblicken und ein besseres Verständnis haben.
Der Haupttext beginnt unten.
[Fall 1] Erhalten Sie das komplette Paket und den Klassennamen über ein Objekt
Paket reflektiert; /*** Erhalten Sie den kompletten Paketnamen und den Klassennamen über ein Objekt***/Klasse Demo {// Andere Codes ...} Klasse Hallo {public static void main (string [] args) {Demo Demo = new Demo (); System.out.println (Demo.getClass (). GetName ()); }}【Auslaufergebnis】: reflektiert.demo
Fügen Sie einen Satz hinzu: Alle Klassenobjekte sind tatsächlich Instanzen der Klasse.
【Fall 2】 Instanziierung des Klassenobjekts
Paket reflektiert; Klasse Demo {// Andere Codes ...} Klasse Hallo {public static void main (String [] args) {Klasse <?> Demo1 = null; Klasse <?> Demo2 = null; Klasse <?> Demo3 = null; Versuchen Sie {// Im Allgemeinen versuchen Sie, dieses Formular zu verwenden. } catch (Ausnahme e) {e.printstacktrace (); } Demo2 = new Demo (). getClass (); Demo3 = Demo.Class; System.out.println ("Klasse name"+Demo1.getName ()); System.out.println ("Klasse name"+Demo2.getName ()); System.out.println ("Klasse name"+Demo3.getName ()); }}【Betriebsergebnisse】:
Klasse namereFlect.demo
Klasse namereFlect.demo
Klasse namereFlect.demo
[Fall 3] Objekte anderer Klassen durch die Klasse instanziieren
Instanziierte Objekte durch Konstruktion von Nicht-Parametern
Paket reflektiert; Klasse Person {public String getName () {return name; } public void setName (String -Name) {this.name = name; } public int getage () {return ay; } public void setage (int age) {this.age = älter; } @Override public String toString () {return "["+this.name+""+this.age+"]"; } privater Zeichenfolge Name; privates int Alter; } class Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } Person per = null; try {per = (Person) Demo.Newinstance (); } catch (InstantiationException e) {// Todo automatisch generierter Catch-Block e.printstacktrace (); } catch (illegalAccessException e) {// Todo automatisch generierter Fangblock E. printstacktrace (); } per.setName ("rollen"); Per.Setage (20); System.out.println (per); }}【Betriebsergebnisse】:
[Rollen 20]
Beachten Sie jedoch, dass wenn wir den parameterlosen Standardkonstruktor in der Person persönlich abbrechen, beispielsweise nach dem Definieren eines Konstruktors mit Parametern ein Fehler auftritt:
Zum Beispiel habe ich einen Konstruktor definiert:
öffentliche Person (String -Name, int age) {this.age = älter; this.name = name; }Dann führen Sie das obige Programm weiter aus, und es wird angezeigt:
java.lang.instantiationException: reflect.person
bei java.lang.class.newinstance0 (class.java:340)
bei java.lang.class.newinstance (class.java:308)
bei reflect.hello.main (hello.java:39)
Ausnahme im Thread "Haupt" java.lang.nullpointerexception
bei reflect.hello.main (hello.java:47)
Wenn Sie also Objekte schreiben, mit denen die Klasse andere Klassen instanziiert, müssen Sie Ihren eigenen Konstruktor ohne Parameter definieren.
[Fall] Rufen Sie Konstruktoren in anderen Klassen über die Klasse auf (Sie können auf diese Weise auch Objekte anderer Klassen durch die Klasse erstellen)
Paket reflektiert; Import Java.lang.reflect.Constructor; Klasse Person {public person () {} public person (String name) {this.name = name; } public Person (int age) {this.age = Alter; } public Person (String -Name, int age) {this.age = älter; this.name = name; } public String getName () {return name; } public int getage () {return ay; } @Override public String toString () {return "["+this.name+""+this.age+"]"; } privater Zeichenfolge Name; private int age;} class Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } Person Per1 = null; Person per2 = null; Person per3 = null; Person per4 = null; // Alle Konstruktoren Konstruktor <?> Cons [] = Demo.getConstructors () erhalten; try {per1 = (Person) cons [0] .Newinstance (); Per2 = (Person) Nachteile [1] .Newinstance ("Rollen"); Per3 = (Person) Nachteile [2] .Newinstance (20); Per4 = (Person) Nachteile [3] .Newinstance ("Rollen", 20); } catch (Ausnahme e) {e.printstacktrace (); } System.out.println (per1); System.out.println (Per2); System.out.println (Per3); System.out.println (Per4); }}【Betriebsergebnisse】:
[NULL 0]
[Rollen 0]
[NULL 20]
[Rollen 20]
【Fall】
Gibt die von einer Klasse implementierte Schnittstelle zurück:
Paket reflektiert; Schnittstelle China {public static Final String name = "Rollen"; öffentliches statisches Int -Alter = 20; öffentliche Void Saychina (); public void SayShello (String -Name, int age);} Klasse Person implementiert China {public Person () {} öffentliche Person (String Sex) {this.sex = sex; } public String getSex () {Return Sex; } public void setsex (String sex) {this.sex = sex; } @Override public void saychina () {System.out.println ("Hallo, China"); } @Override public void SayShello (String -Name, int age) {System.out.println (Name+""+Alter); } private String sex;} class Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } // Alle Schnittstellenklassen <?> Inten [] = Demo.getInterfaces () speichern; für (int i = 0; i <ines.Length; i ++) {System.out.println ("implementierte Schnittstelle"+innes [i] .getName ()); }}}【Betriebsergebnisse】:
Implementierte Schnittstelle reflektiert.china
(Beachten Sie, dass die folgenden Beispiele die Personenklasse dieses Beispiels verwenden. Um Platz zu sparen, werden wir hier nicht mehr den Personen -Code -Teil einfügen, sondern nur den Code der Hauptklasse Hallo))
【Fall】: Holen Sie sich die übergeordnete Klasse in anderen Klassen
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } // Holen Sie sich die übergeordnete Klasse Class <?> Temp = Demo.getSuperClass (); System.out.println ("Die ererbte übergeordnete Klasse ist:"+temp.getName ()); }}【Auslaufergebnisse】
Die ererbte Elternklasse lautet: java.lang.object
【Fall】: Erhalten Sie alle Konstruktoren in anderen Klassen
Dieses Beispiel erfordert das Hinzufügen von Import Java.lang.reflect.* Zu Beginn des Programms;
Schreiben Sie dann die Hauptklasse als:
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } Constructor <?> Cons [] = Demo.getConstructors (); für (int i = 0; i <con.Length; i ++) {System.out.println ("Konstruktor:"+cons [i]); }}}【Betriebsergebnisse】:
Konstruktionsmethode: öffentlich reflektiert.person ()
Konstruktor: Public Reflect.person (Java.lang.String)
Sorgfältige Leser werden jedoch feststellen, dass der obige Konstruktor keine Modifikatoren wie öffentlich oder privat hat
Lassen Sie uns den Modifikator im folgenden Beispiel erhalten
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } Constructor <?> Cons [] = Demo.getConstructors (); für (int i = 0; i <con.Length; i ++) {class <?> p [] = cons [i] .getParameterTypes (); System.out.print ("Konstruktor:"); int mo = cons [i] .getModifierer (); System.out.print (modifier.toString (mo)+""); System.out.print (cons [i] .getName ()); System.out.print ("("); für (int j = 0; j <p.Length; ++ j) {System.out.print (p [j] .getName ()+"arg"+i); if (j <P.Length-1) {System.out.print (",");}} system.println (") {{{{{{{{{{{{{{{}); }}【Betriebsergebnisse】:
Konstruktor: public reflect.person () {}
Konstruktor: public reflect.person (java.lang.string arg1) {}
Manchmal kann es Ausnahmen in einer Methode geben, haha. Schauen wir uns an:
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } Method -Methode [] = Demo.getMethods (); für (int i = 0; i <method.length; ++ i) {class <?> returnType = methode [i] .getReturnType (); Klasse <?> Para [] = Methode [i] .GetParameterTypes (); int temp = methode [i] .getModifiers (); System.out.print (modifier.toString (temp)+""); System.out.print (returnTyPe.getName ()+""); System.out.print (Methode [i] .getName ()+""); System.out.print ("("); für (int j = 0; j <para.length; ++ j) {System.out.print (para [j] .getName ()+""+"arg"+j); if (j <para.Length-1) {System.out.print (","); if (exce.length> 0) {System.out.print (") löscht"); für (int k = 0; k <exce.length; ++ k) {System.out.print (exce [k] .getName ()+""); if (k <exce.length-1) {System.out.print (","); }}} else {System.out.print (")"); } System.out.println (); }}}【Betriebsergebnisse】:
Public Java.lang.String GetSex ()
öffentliches void setsex (java.lang.string arg0)
Öffentliche Void Saychina ()
Öffentliche void Sayshello (Java.lang.String arg0, int arg1)
öffentliche endgültige native void wait (long arg0) wirft java.lang.interruptedException aus
Öffentliche Finale void Wait () wirft java.lang.interruptedException aus
Öffentliche Finale Leere Wartezeit (Long Arg0, int arg1) wirft java.lang.interruptedException aus
öffentlicher Boolescher gleich (Java.lang.Object arg0)
Public Java.lang.String ToString ()
öffentliche native int hashcode ()
Public Final Native Java.lang.Class getClass ()
öffentliche endgültige native void mellify ()
öffentliche endgültige native void notifyall ()
[Fall] Als nächstes erhalten wir alle Eigenschaften anderer Klassen. Schließlich werde ich sie zusammen aussortieren, das heißt, den gesamten Rahmen einer Klasse durch die Klasse zu bekommen
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } System.out.println("=========================================================================================== =================================================================ieben =================================================================ieben ============================================================ieben Berechtigungsmodifikator int MO = Field [i] .GetModifiers (); System.out.println("====================================================================================== ==================================================================ieben ==================================================================ieben ==================================================================ieben füleed1 = Demo.getFields (); für (int j = 0; j <fileed1.length; j ++) {// Berechtigungsmodifikator int mo = fehlerhaft [j] .GetModifiers (); String priv = modifier.toString (MO); // Eigenschaftstypklasse <?> Type = fehled1 [j] .Getype (); System.out.println (priv + "" " + type.getName () +" " + fileed1 [j] .getName () +"; "); }}}【Betriebsergebnisse】:
======================================================
Privat Java.lang.String Sex;
==============================================================
Public Static Final Java.lang.String Name;
öffentliches statisches Endalter;
[Fall] Tatsächlich können Methoden in anderen Klassen auch durch Reflexion aufgerufen werden:
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } try {// Die Saychina -Methode in der Personklassenmethode aufrufen = Demo.getMethod ("Saychina"); method.invoke (Demo.Newinstance ()); // Die Sayhello -Methode der Person nennen. method.invoke (Demo.Newinstance (), "Rollen", 20); } catch (Ausnahme e) {e.printstacktrace (); }}}【Betriebsergebnisse】:
Hallo China
Rollen 20
【Fall】 Rufen Sie die Methoden anderer Klassen auf und erhalten Sie Methoden
Klasse Hallo {public static void main (String [] args) {class <?> Demo = null; Objekt obj = null; try {Demo = class.forname ("reflect.person"); } catch (Ausnahme e) {e.printstacktrace (); } try {obj = Demo.Newinstance (); } catch (Ausnahme e) {e.printstacktrace (); } setter (obj, "sex", "männlich", string.class); Getter (obj, "Sex"); } / ** * @param obj * Operation Objekt * @param att * Attribute der Operation * * / public static void getter (Object OBJ, String att) {try {method method = obj.getClass (). getMethod ("get" + att); System.out.println (method.invoke (obj)); } catch (Ausnahme e) {e.printstacktrace (); }} / ** * @param obj * Objekt der Operation * @param att * Attribute der Operation * @param value * Set Value * @param Typ * Attribute des Parameters * * / public static void setter (Objekt obj, String att, Objektwert, Klasse <> type) {try {method method = obj.getClass (). method.invoke (obj, Wert); } catch (Ausnahme e) {e.printstacktrace (); }}} // Endklasse【Betriebsergebnisse】:
männlich
【Fall】 Operation durch Reflexion
Klasse Hallo {public static void main (String [] args) löst eine Ausnahme aus {class <?> Demo = null; Objekt obj = null; Demo = class.Forname ("reflect.person"); obj = Demo.Newinstance (); Field Field = Demo.GetDeclaredfield ("Sex"); field.setAccessible (true); field.set (obj, "männlich"); System.out.println (field.get (obj)); }} // Ende der Klasse[Fall] die Informationen des Arrays durch Reflexion erhalten und ändern:
Java.lang.reflect.*; Klasse Hallo {public static void main (String [] args) {int [] temp = {1,2,3,4,5}; Klasse <?> Demo = temp.getClass (). GetComponentType (); System.out.println ("Array Typ:"+Demo.getName ()); System.out.println ("Array Länge"+Array.getLength (temp)); System.out.println ("Erstes Element des Arrays:"+array.get (temp, 0)); Array.set (temp, 0, 100); System.out.println ("Nachdem das erste Element des Arrays geändert wurde ist:"+array.get (temp, 0)); }}【Betriebsergebnisse】:
Array -Typ: int
Arraylänge 5
Das erste Element des Arrays: 1
Nach der Änderung ist das erste Element des Arrays: 100
【Fall】 Ändern Sie die Arraygröße durch Reflexion
Klasse Hallo {public static void main (String [] args) {int [] temp = {1,2,3,4,5,6,7,8,9}; int [] newTemp = (int []) arrayinc (temp, 15); print (newTemp); System.out.println("================================================================================= ===========================================================ieben String []) Arrayinc (ATR, 8); System.ArrayCopy (OBJ, 0, Newarr, co); Array.getLength (obj);【Betriebsergebnisse】:
Die Arraylänge ist: 15
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 ========================================
Die Arraylänge ist: 8
ABC NULL NULL NULL NULL NULL
Dynamischer Agent
[Fall] Schauen wir uns zunächst an, wie Sie den Klassenloader erhalten:
Klasse test {} class Hallo {public static void main (String [] args) {test t = new Test (); System.out.println ("classloader"+t.getClass (). GetClassloader (). GetClass (). GetName ()); }}【Programmausgabe】:
Klasse Loader sun.misc.launcher $ AppClassloader
Tatsächlich gibt es in Java drei Arten von Klassenladern.
1) Bootstrap Classloader Dieser Loader ist in C ++ geschrieben und ist in der allgemeinen Entwicklung selten zu sehen.
2) Der Erweiterungsklassenloader wird verwendet, um erweiterte Klassen zu laden, die im Allgemeinen Klassen im JRE/LIB/EXT -Verzeichnis entsprechen
3) AppClassloader lädt die von ClassPath angegebene Klasse und ist der am häufigsten verwendete Lader. Es ist auch der Standardlader in Java.
Wenn Sie einen dynamischen Proxy absolvieren möchten, müssen Sie zunächst eine Unterklasse der InvocationHandler -Schnittstelle definieren, und der spezifische Betrieb des Proxy wurde abgeschlossen.
Paket reflektiert; import Java.lang.reflect.*; // Project Interface Interface Betreff {public String sagt (String -Name, int ARTER);} // Definieren Sie die reale Projektklasse RealSubject implements Betreff {@Override public String Says (String -Name, int Age) {Rückgabename + " + Alter; }} class myInvocationHandler implementiert invocationHandler {private Object obj = null; öffentliches Objekt Bind (Objekt obj) {this.obj = obj; return proxy.newProxyInstance (obj.getClass (). getClassloader (), obj .getClass (). getInterfaces (), dies); } @Override public Object Invoke (Object Proxy, Methode Methode, Object [] args) wirft Throwable {Object temp = method.invoke (this.obj, args) aus; Temperatur zurückgeben; }} class Hallo {public static void main (String [] args) {myInvocationHandler Demo = new myInvocationHandler (); Subjekt sub = (Subjekt) Demo.bind (new RealSubject ()); String info = sub.say ("Rollen", 20); System.out.println (info); }}【Betriebsergebnisse】:
Rollen 20
Der Lebenszyklus einer Klasse
Nachdem eine Klasse zusammengestellt wurde, besteht der nächste Schritt darin, die Klasse zu verwenden. Wenn Sie eine Klasse verwenden möchten, ist sie definitiv unzertrennlich von JVM. Während der Programmausführung wird die JVM in diesen drei Schritten abgeschlossen: Laden, Verknüpfung und Initialisierung.
Die Klassenbelastung erfolgt über einen Klassenlader. Der Loader lädt die Binärdatei der .class -Datei in den JVM -Methodenbereich und erstellt ein java.lang.Class -Objekt, das diese Klasse im Haufenbereich beschreibt. Wird verwendet, um Daten zu verkapulieren. Die gleiche Klasse wird jedoch nur vom Klassenlader zuvor geladen
Links sollen binäre Daten in einen Zustand zusammenstellen, der ausgeführt werden kann.
Die Verbindung ist in drei Stufen unterteilt: Überprüfung, Vorbereitung und Parsen
Die Überprüfung wird im Allgemeinen verwendet, um zu bestätigen, ob diese Binärdatei für die aktuelle JVM (Version) geeignet ist.
Die Vorbereitung soll den statischen Mitgliedern Speicherplatz bereitstellen. und Standardwerte festlegen
Parsing bezieht sich auf den Prozess der Konvertierung des Code im konstanten Pool als direkte Referenz, bis alle symbolischen Referenzen vom laufenden Programm verwendet werden können (eine vollständige Korrespondenz festlegen)
Nach Abschluss wird der Typ initialisiert. Nach der Initialisierung kann das Objekt der Klasse normal verwendet werden. Nachdem ein Objekt nicht mehr verwendet wurde, wird es Müll gesammelt. Platz frei machen.
Wenn kein Bezugspunkt auf das Klassenobjekt zeigt, wird es deinstalliert und beendet den Klassenlebenszyklus
Verwenden Sie die Reflexion für den Werksmodus
Schauen wir uns den Werksmodus an, wenn Sie keine Reflexion benötigen:
http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144851.html
/ *** @Author Rollen-Holt Factory-Modus des Entwurfsmusters*/ Schnittstelle Frucht {public abstract void eat ();} Klasse Apfel implementiert Obst {public void Eat () {System.out.println ("Apfel"); }} Klasse Orange implementiert Frucht {public void eat () {System.out.println ("orange"); }} // Konstruktieren Sie die Fabrikklasse // Mit anderen Worten, wenn wir die Fabrikklasse nur ändern müssen, wenn wir andere Instanzen in der zukünftigen Klassenfabrik hinzufügen {öffentliche statische Frucht GetInstance (String Fruitname) {fruit f = null; if ("apple" .equals (fruitname)) {f = new Apple (); } if ("orange" .equals (fruitname)) {f = new Orange (); } return f; }} Klasse Hallo {public static void main (String [] a) {fruit f = factory.getInstance ("orange"); f.eat (); }}Auf diese Weise müssen wir, wenn wir eine Unterklasse hinzufügen, die Fabrikklasse ändern. Wenn wir zu viele Unterklassen hinzufügen, werden wir uns viel ändern.
Schauen wir uns nun den nutzenden Reflexionsmechanismus an:
Paket reflektiert; Schnittstelle Frucht {public abstract void eat ();} Klasse Apfel implementiert Frucht {public void eat () {System.out.println ("Apple"); }} Klasse Orange implementiert Frucht {public void eat () {System.out.println ("orange"); }} class Factory {public statische Frucht GetInstance (String ClassName) {fruit f = null; try {f = (frucht) class.forname (className) .Newinstance (); } catch (Ausnahme e) {e.printstacktrace (); } return f; }} Klasse Hallo {public static void main (String [] a) {fruit f = factory.getInstance ("reflect.apple"); if (f! = null) {f.eat (); }}}Selbst wenn wir so viele Unterklassen hinzufügen, muss die Fabrikklasse nicht geändert werden.
Obwohl die obige Liebe durch Reflexion eine Instanz der Schnittstelle erhalten kann, muss sie im kompletten Paket- und Klassennamen übergeben. Darüber hinaus können Benutzer nicht wissen, wie viele Unterklassen in einer Schnittstelle verwendet werden können. Daher konfigurieren wir die erforderlichen Unterklassen in Form von Attributdateien.
Schauen wir uns an: Factory -Modus kombiniert Attributdateien
Erstellen Sie zuerst eine Ressourcendatei fruit.properties.
Inhalt sind:
Apple = reflektiert.Apple
orange = reflect.orange
Schreiben Sie dann den Hauptklassencode:
Paket reflektiert; Java.io importieren.*; import Java.util.*; Schnittstelle Frucht {public abstract void eat ();} Klasse Apfel implementiert Frucht {public void eat () {System.out.println ("Apple"); }} Klasse Orange implementiert Frucht {public void eat () {System.out.println ("orange"); }} // Betriebseigenschaftsdateiklasse init {public statische Eigenschaften getPro () löscht FilenotFoundException, IOException {Properties pro = new Properties (); Datei f = neue Datei ("fruit.properties"); if (f.exists ()) {pro.load (neuer FileInputStream (f)); } else {pro.setProperty ("Apple", "Reflect.Apple"); pro.setProperty ("orange", "reflect.orange"); Pro.Store (neuer FileOutputStream (f), "Fruchtklasse"); } return pro; }} class Factory {public statische Frucht GetInstance (String ClassName) {fruit f = null; try {f = (frucht) class.forname (className) .Newinstance (); } catch (Ausnahme e) {e.printstacktrace (); } return f; }} class Hello {public static void main (String [] a) löscht FilenotFoundException, ioException {properties pro = init.getPro () aus; frucht f = factory.getInstance (pro.getProperty ("Apple"); if (f! = null) {f.eat (); }}}【Laufen Ergebnis】: Apfel
Das obige ist eine detaillierte Erklärung des Java -Reflexionsmechanismus. Wir werden in Zukunft weiterhin relevante Informationen hinzufügen. Vielen Dank für Ihre Unterstützung für diese Seite!