Als ich anfing, Java zu lernen, war es wirklich schwierig zu verstehen, was Reflexion ist.
Manche Bücher, auch sehr klassische, erklären Dinge auf eine Weise, die die Leute verwirrt. Vielleicht bin ich einfach zu dumm.
Darüber hinaus heißt es im Internet, dass der Reflexionsmechanismus beim Erlernen von Frameworks in Zukunft häufig verwendet werden muss, was bei den Menschen immer ein wenig Unbehagen hervorruft.
Ich habe mir zufällig einige Kapitel und Videos angesehen, in denen die Reflexion erklärt wird, und ich denke, ich kann es etwas besser verstehen.
Jetzt habe ich beschlossen, hart zu arbeiten, gleichzeitig zu lesen und zu schreiben und hier einige wichtige Inhalte und Vorgänge aufzuzeichnen.
Ich denke, für einen dummen Menschen wie mich ist das Wiederholen vielleicht der beste Weg, etwas zu lernen
Wenn ich auf etwas stoße, das ich nicht verstehe, höre ich auf und lerne es noch einmal. Obwohl es viel Zeit verschwendet, hat es auch eine gewisse Wirkung auf mich.
Mein Verständnis ist: Die sogenannte Reflexion besteht darin, die vollständigen Informationen der Klasse basierend auf einem bereits instanziierten Objekt wiederherzustellen.
Zumindest für mich besteht der Vorteil darin, dass ich die Objektorientierung von Grund auf verstehen kann.
x_x Hier hasse ich diese dicken Köpfe wieder, sie haben alle meine Gehirnzellen getötet.
Klasse KlasseWenn Sie die Reflexion abschließen möchten, müssen Sie die Klasse Class verstehen
Beispiel 1: Erhalten Sie den Paketnamen und den Klassennamen über das ObjektKlassentest {
}
Demo der öffentlichen Klasse {
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.getClass());
System.out.println(t.getClass().getName());
}
}
Die Kompilierungsergebnisse sind wie folgt. Achten Sie nur darauf, wie das Paket kompiliert wird.
Die Methode getClass() wird hier standardmäßig von der Object-Klasse geerbt.
In Java ist die Object-Klasse die übergeordnete Klasse aller Klassen. Ebenso sind die instanziierten Objekte aller Klassen auch Instanzen der Class-Klasse.
Daher wird es hier um die Konzepte der Aufwärtstransformation und der Abwärtstransformation gehen
Aufgrund der Unsicherheit der Abwärtswürfe werden auch hier Generika folgen.
(Aber was ich sagen möchte ist, dass das generische Design hier sehr umwerfend ist! Verdammt, das Syntaxdesign des gesamten Java ist auch umwerfend, super ekelhaft!!!)
Beispiel 2: Instanziierung der Klasse classDa die Class-Klasse keinen Konstruktor hat, ist die Methode zum Instanziieren der Class-Klasse etwas speziell. Es gibt drei Möglichkeiten:
Object.getClass()}
Demo der öffentlichen Klasse {
public static void main(String[] args) {
//Methode 1:
Test t = new Test();
Class<? erweitert Test> c1 = t.getClass();
System.out.println(c1);
//Methode 2:
// Um Spezifität zu vermeiden, wird hier nicht die Testklasse, sondern die String-Klasse in der Java-Bibliothek verwendet.
Class<String> c2 = String.class;
System.out.println(c2);
//Methode 3:
Die Methode //forName() löst eine Ausnahme aus
Klasse<?> c3 = null;
versuchen {
c3 = Class.forName("Test");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println(c3);
}
}
In der Class-Klasse gibt es eine Methode namens newInstance(), mit der eine neue Instanz des Class-Klassenobjekts erstellt werden kann
Wie sagt man es? Der im Klassenobjekt enthaltene Inhalt ist die reflektierte Klasse. Wir müssen eine neue Instanz (neues Objekt) dieser Klasse erstellen.
Beispiel 3: Konstruieren eines Objekts ohne Parameter der Klassenklasse //Erzeuge einen Verweis auf einen String
Zeichenfolge s = null;
versuchen {
//Das konstruierte Objekt in die String-Klasse umwandeln
Die Methode //newInstance() löst eine Ausnahme aus
s = (String) c.newInstance();
} Catch (InstantiationException e) {
e.printStackTrace();
} Catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println("String length: " + s.length());
}
}
Dadurch wird ein neues Objekt in einer parameterlosen Form erstellt, genau wie im normalen Modus
Das Erstellen eines neuen Objekts über den Konstruktor ohne Argumente ist dasselbe wie
Wir wissen, dass es in einer Klasse neben parameterlosen Konstruktoren auch parametrisierte Konstruktoren gibt.
Wie konstruiert man also Objekte in Form von Parametern in der Reflexion? Lesen Sie weiter
Beispiel 4: Parametrisiertes konstruiertes Objekt der Klasse Klasse Demo der öffentlichen Klasse {
// Die folgenden Methoden lösen zu viele Ausnahmen aus. Aus Gründen der Codekompaktheit werden sie hier direkt an die virtuelle Maschine geworfen.
public static void main(String[] args) löst eine Ausnahme aus {
Klasse<?> c = null;
versuchen {
c = Class.forName("java.lang.String");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
char[] ch = {'h','e','l','l','o'};
Zeichenfolge s = null;
//Den parametrisierten Konstruktor des Klassenobjekts abrufen. Die Parameter in den Klammern werden wie folgt geschrieben: type.class
Constructor<?> con = c.getConstructor(char[].class);
// Verwenden Sie diese Konstruktionsmethode, um ein neues String-Objekt zu erstellen. Der Parameter ist ein char-Array
s = (String) con.newInstance(ch);
System.out.println("Konstruierte Zeichenfolge: " + s);
}
}
Wir verwenden weiterhin die String-Klasse als Beispiel, da die String-Klasse häufiger verwendet wird und leichter zu verstehen ist.
Hierbei ist zu beachten, dass der Konstruktor mit der Methode getConstructor() abgerufen werden muss
Der Parametertyp lautet: Originaltyp.Klasse
Ein weiterer Punkt ist, dass die hier verwendete Konstruktionsmethode unabhängig davon, ob sie Parameter hat oder nicht, in der ursprünglichen Klasse vorhanden sein muss.
Wie können wir also die detaillierten Informationen wie die Konstruktormethode, die gewöhnliche Methode, die geerbte übergeordnete Klasse usw. in der ursprünglichen Klasse kennen? Lesen Sie weiter
Holen Sie sich die Struktur der KlasseUm die Struktur einer Klasse durch Reflektion zu erhalten, müssen wir ein neues Paket java.lang.reflect importieren
Beispiel 5: Erhalten Sie den Konstruktor einer Klasse Demo der öffentlichen Klasse {
// Die folgenden Methoden lösen zu viele Ausnahmen aus. Aus Gründen der Codekompaktheit werden sie hier direkt an die virtuelle Maschine geworfen.
public static void main(String[] args) löst eine Ausnahme aus {
Klasse<?> c = null;
versuchen {
c = Class.forName("java.lang.Boolean");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Die Methode getConstructors() gibt hier ein Konstruktor-Array zurück
Constructor<?>[] cons = c.getConstructors();
//Sie können die Druckmethode selbst schreiben. Der Einfachheit halber verwende ich Arrays.toString().
System.out.println(Arrays.toString(cons));
}
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Klasse<?> c = null;
versuchen {
c = Class.forName("java.lang.Boolean");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
Klasse<?>[] in = c.getInterfaces();
System.out.println(Arrays.toString(in));
}
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Klasse<?> c = null;
versuchen {
c = Class.forName("java.lang.Boolean");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
Methode[] m = c.getMethods();
//Okay, dieses Mal werde ich gnädig sein und eine Ausdruckliste schreiben.
for (int i = 0; i < m.length; i++) {
System.out.println(m[i]);
}
}
}
Klasse Person {
privater String-Name;
privates Int-Alter;
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Klasse<?> c = null;
versuchen {
c = Class.forName("Person");
} Catch (ClassNotFoundException e) {
e.printStackTrace();
}
Field[] f = c.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
System.out.println(f[i]);
}
}
}
Die Methode getDeclaredFielsd() kann alle Eigenschaften abrufen, und getFields() kann nur öffentliche Eigenschaften abrufen.
Beispiel 10: Rufen Sie den Wert des Attributs in dieser Klasse ab Klasse Person {
öffentlicher String-Name;
privates Int-Alter;
öffentliche Person(String name, int age) {
this.name = Name;
this.age = Alter;
}
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Person p = neue Person("zhangsan",12);
Klasse<?> c = p.getClass();
//Den Wert des öffentlichen Attributs abrufen
Feld f1 = c.getField("name");
//get(p) gibt an, welcher Objektwert erhalten werden soll
String str = (String) f1.get(p);
System.out.println("Name: " + str);
//Den Wert des privaten Attributs abrufen
Feld f2 = c.getDeclaredField("age");
//age ist eine private Eigenschaft, also setzen Sie die Sicherheitsüberprüfung auf true
f2.setAccessible(true);
int age = (int) f2.get(p);
System.out.println("Alter: " + Alter);
}
}
Ehrlich gesagt habe ich in Java keine Kenntnisse gefunden, die meine Titanaugen blenden könnten.
Jedes Mal muss ich eine Menge mühsamer Syntax schreiben, um ein Gadget zu implementieren, oder ich muss verzweifelt die API aufrufen und verzweifelt Ausnahmen auslösen.
Machen Sie Code, der nicht kompakt genug ist, umständlich
Wenn mir eine Sprache gefällt, müssen mich ihre eigenen Eigenschaften beeindrucken, bevor ich daraus etwas machen kann.
Offensichtlich macht mich Java nicht glücklich. Vielleicht sind viele Programmierer wie ich gezwungen, Java zu verwenden.
Um mein einsames Programmierherz zu beruhigen, lesen Sie weiter unten
Reflection-Anwendungsbeispiel 11: Attribute durch Reflection ändern Klasse Person {
privater String-Name;
öffentliche Person(Stringname) {
this.name = Name;
}
öffentlicher String toString() {
return „Name:“ + this.name;
}
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Person p = new Person("王二狗");
System.out.println(p);
Klasse<?> c = p.getClass();
//Definieren Sie die zu ändernden Eigenschaften
Feld f = c.getDeclaredField("name");
f.setAccessible(true);
//Eigenschaften ändern und das festzulegende Objekt und den Wert übergeben
f.set(p, „Zhang Erdan“);
System.out.println(p);
}
}
Klasse Person {
public void print(int i) {
System.out.println("Ich schreibe Zahlen: " + i);
}
public static void say(String str) {
System.out.println("Ich sage: " + str);
}
}
Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
Person p = neue Person();
Klasse<?> c = p.getClass();
Die //getMethod()-Methode muss den Methodennamen und den Parametertyp übergeben
Methode m1 = c.getMethod("print", int.class);
//invoke() bedeutet Aufruf und muss Objekte und Parameter übergeben
m1.invoke(p, 10);
Methode m2 = c.getMethod("say", String.class);
// Die Null bedeutet hier, dass sie nicht vom Objekt aufgerufen wird, also eine statische Methode ist
m2.invoke(null, „deine Schwester“);
}
}
Hier ist eine Demonstration einer normalen parametrisierten Methode und einer statischen Methode
Da nun alle Parameter ausgeschrieben sind, ist es für diejenigen ohne Parameter noch einfacher, einfach ein Objekt direkt zu übergeben.
Beispiel 13: Arrays durch Reflexion manipulieren Demo der öffentlichen Klasse {
public static void main(String[] args) löst eine Ausnahme aus {
int[] arr = {1,2,3,4,5};
Class<?> c = arr.getClass().getComponentType();
System.out.println("Array-Typ: " + c.getName());
int len = Array.getLength(arr);
System.out.println("Array-Länge: " + len);
System.out.print("Durchlaufen Sie das Array:");
for (int i = 0; i < len; i++) {
System.out.print(Array.get(arr, i) + " ");
}
System.out.println();
//Array ändern
System.out.println("Das erste Element vor der Änderung: " + Array.get(arr, 0));
Array.set(arr, 0, 3);
System.out.println("Das geänderte erste Element: " + Array.get(arr, 0));
}
}
Das ist vorerst alles. Das Buch, das ich gelesen habe, beinhaltet auch die Anwendung der Reflexion im Fabrikmodus.
Es ist nichts weiter, als es durch die Methode forName() zu ersetzen. Da gibt es nicht viel zu sagen.
Ich bin ein Java-Anfänger. Ich hasse die eklige Syntax und das Design von Java.
Dies ist alles für Android, um den Grundstein zu legen und sich an zukünftige Arbeiten anzupassen.