Vorwort
Ich habe mir Java
vor vielen Jahren Notizen zum Thema Reflexion gemacht. Nach all den Jahren, in denen ich Reflexion verwende, lese ich nur noch dieses.
Da es jedoch umständlich ist, Notizen in Form von Dateien zu speichern, habe ich sie abgelegt CSDN
und hoffe, damit mehr Freunden helfen zu können.
Klasse Klasse
Java
Jede Klasse im Programm gehört zur gleichen Art von Dingen, und der Klassenname, Java
der diese Art von Dingen beschreibt , lautetJava
Class
Person -> Person
Java-Klasse -> Klasse
Rufen Sie das Instanzobjekt ab, das jedem Bytecode entspricht
Methode 1: Klassenname:class
Class cls1 = Person.class;
Methode 2: Objekt:getClass
Class cls2 = p1.getClass();
Methode drei:forName
Class cls3 = Class.forName("java.lang.String");
Methode vier:getClassLoader().getClass
Class clazz = getClassLoader().getClass("java.lang.String");
Der Unterschied zwischen .class(), getClass(), Class.forName(), getClassLoader()
.class
ist die Klasse beim Abrufen der Deklaration.
getClass()
ist die Klasse, die die Laufzeit erhält.
Class.forName()
Die Klasse wird über den Klassennamen ermittelt.
getClassLoader()
ist der Loader, der die Klasse erhält.
Wenn der Bytecode zuvor geladen wurde, befindet er sich bereits in Java
der virtuellen Maschine und Sie können direkt zurückkehren, z. B. Methode 1 und Methode 2.
Wenn Java
der Bytecode nicht in der virtuellen Maschine vorhanden ist, laden Sie ihn mit dem Klassenlader Der Bytecode wird in der virtuellen Maschine zwischengespeichert. In Zukunft muss dieser Bytecode nicht mehr geladen werden, z. B. bei Methode 3
vordefiniertes Objekt
Es gibt 9
vordefinierte Objekte, 8
primitive Typen undvoid
Class class1 = boolean.class;
Class class2 = int.class;
//.......
Class class3 = Void.class;
Verwenden Sie diese Option isPrimitive
, um zu beurteilen, ob es sich um einen Basistyp handelt
int.class.isPrimitive
Verwenden Sie diese Option isArray
, um zu beurteilen, ob es sich um ein Array handelt
int[].class.isArray
Typ abrufen
getclass().getName();
Betrachtung
Bei der Reflexion werden Java
verschiedene Komponenten in einer Klasse den entsprechenden Java
Klassen zugeordnet
Field
:Membervariable
Method
:Methode
Constructor
:Konstruktor
Package
:Paket
Konstrukteur
Holen Sie sich alle Konstruktoren einer Klasse
Class.forName("java.lang.String").getConstructors();
Holen Sie sich einen Konstruktor
Geben Sie den entsprechenden Konstruktor gemäß den Parametern in getConstructor zurück
Class.forName("java.lang.String").getConstructor(StringBuffer.class);
Was kann ein Konstrukteur tun?
Holen Sie sich das Instanzobjekt (man constructor
kann new
unzählige Instanzobjekte erzeugen)
(强制转换)constructor1.newInstance(参数要和getConstructor中的一致);
Erstellen Sie eine Instanz mit der Standardkonstruktionsmethode (die Instanz wird intern zwischengespeichert und beim zweiten Erwerb nicht erneut erstellt, sondern direkt erfasst).
String obj = (String) Class.frName("java.lang.String").newInstance();
Der ursprüngliche Reflexionsschritt besteht darin,
Class -> Constructor -> newInstance
ihnClass.newInstance()
direkt im Inneren zu verwendenConstructor
, dhClass -> Class.newInstance()
Sie können die Instanz des Standardkonstruktors direkt abrufen
Feld
Stellt eine Mitgliedsvariable in einer Klasse dar
Personenklasse
public class Person {
public String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Erhalten Sie Mitgliedsvariablen durch Reflexion
Person person = new Person();
person.setAge(20);
person.name = "Heiko";
//Field fieldName = person.getClass().getField("name"); 都可以
Field fieldName = Class.forName("reflectTest.Person").getField("name");
//fieldName的值为多少?不是Heiko,因为fieldName不是对象身上的变量,而是类上,要通过field.get("实例")或getDeclaredField来获取该实例上的值
String name = (String) fieldName.get(person);
System.out.println("name:" + name);
//对于私有变量,需暴力破解
Field fieldAge = person.getClass().getDeclaredField("age"); //getDeclaredField 不管是私有还是public的,都可以获取
fieldAge.setAccessible(true); //设置可以访问 fieldAge.get("age")
int age = (int) fieldAge.get(person);
System.out.println("age:" + age);
Holen Sie sich eine statische Variable
Field filed = obj.getClass().getField(cmdFieldName);
Integer cmdValue = (Integer) filed.get(null); //获取静态变量
Holen Sie sich alle Mitgliedsvariablen
obj.getClass().getFields();
Der Unterschied zwischen getFields und getDeclaredFields
getFields()
getDeclaredFields()
: Kann nur auf die in der Klasse als öffentlich deklarierten Felder zugreifen, auf private Felder kann nicht zugegriffen werden, aber auf öffentliche Methoden, die von anderen Klassen geerbt wurden: Kann auf alle Felder in der Klasse zugreifen, unabhängig von der Beziehung, nicht auf Methoden zugreifen, die von anderen Klassen public,private,protect
geerbt wurden
Vergleichen Sie Mitgliedsvariablentypen
if(field.getType() == String.class)
Einstellungen
field.set(obj,新的值);
Ersetzen Sie das b des Mitgliedsvariablenwerts vom Typ String in der Instanz durch a
//将对象中的String类型的成员变量所有的字符b换为字符a
private static void exchangeCharValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();
for(Field field : fields){
//if(field.getType().equals(String.class)){
if(field.getType() == String.class){
//这里用 == 比equals更准确,字节码只有一份自己和自己比较
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
Methode
Stellt eine Mitgliedsmethode in einer Klasse dar
method.invoke(owner, args):
owner
: Das Objekt, das diese Methode ausführt, args: Parameter, der wie folgt verstanden werden kann: Die Methodenmethode mit Parameter args im Besitzerobjekt.- Der Rückgabewert ist Object, was auch der Rückgabewert dieser Methode ist.
String s = "abc";
Method methodCharAt = String.class.getMethod("charAt", int.class);
String newString =methodCharAt.invoke(s, 1);//invoke是方法身上的方法,s是执行该方法的对象(必须是实例化的对象)
System.out.println(newString);
Rufen Sie die statische Methode auf
methodCharAt.invoke(null, 值);
Reflexionsarray
- Wenn die Abmessungen des Arrays (eindimensional, zweidimensional usw.) und der Array-Typ gleich sind, sind ihre Bytecodes gleich
- Die übergeordnete Klasse, die von der getSuperClass()-Methode des das Array darstellenden Klasseninstanzobjekts zurückgegeben wird, ist die Klasse, die der Objektklasse entspricht
- Ein eindimensionales Array von Basistypen kann als Objekttyp verwendet werden, jedoch nicht als Objekt[]-Typ
- Eindimensionale Arrays von Nicht-Basistypen können als Object-Typen oder als Object[]-Typen verwendet werden
Der Unterschied zwischen int[] und String[] bei ArrayList.asList
Da es den Typ asList
empfängt , es sich jedoch nicht um den Typ handelt, wird es für die nachfolgende Verarbeitung als Objekt behandeltObject[]
int[]
Object[]
jdk1.5
asList(T...t)
int[]
Arrays.asList(new int[]{
1,2,3}); //打印内容为:[@hascode]
Arrays.asList(new String[]{
"1","2","3"}); //打印内容为:[1,2,3]
Array-Reflektionsanwendung
Ausgabearray
private static void printObject(Object obj) {
Class clazz = obj.getClass();
if (clazz.isArray()) {
//如果是数组
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
System.out.println(Array.get(obj, i));
}
} else {
System.out.println(obj);
}
}
überweisen
String[] array = new String[] {
"1", "2", "3" };
String valueString = "test";
printObject(array);
printObject(valueString);