Heim  >  Artikel  >  Java  >  So verstehen Sie die Java-Reflexion

So verstehen Sie die Java-Reflexion

藏色散人
藏色散人Original
2019-11-13 10:19:372900Durchsuche

So verstehen Sie die Java-Reflexion

Wie versteht man Java-Reflexion?

Übersicht

Java Reflection ist ein Mechanismus, der es uns ermöglicht, interne Informationen von Klassen wie Methoden, Eigenschaften, übergeordneten Klassen, Schnittstellen usw. zu erhalten Laufzeit. Mit anderen Worten: Reflexion ist im Wesentlichen ein „umgekehrter“ Prozess. Wenn wir eine Instanz einer Klasse über new erstellen, wird sie zur Laufzeit tatsächlich von der virtuellen Java-Maschine basierend auf dem Klassenobjekt dieser Klasse erstellt, und die Reflexion erhält ihre Definitionsinformationen über das Klassenobjekt einer Klasse, sodass wir darauf zugreifen können Gehen Sie zu seinen Attributen und Methoden, kennen Sie die übergeordnete Klasse dieser Klasse, welche Schnittstellen implementiert sind und andere Informationen.

Klassenklasse

Wir wissen, dass Javac zum Kompilieren von .java-Dateien in .class-Dateien verwendet werden kann. Diese .class-Datei enthält unsere ursprünglichen Definitionsinformationen der Klasse (. übergeordnete Klassen, Schnittstellen, Konstruktoren, Eigenschaften, Methoden usw.). Die .class-Datei wird zur Laufzeit vom ClassLoader in die Java Virtual Machine (JVM) geladen. Wenn eine .class-Datei geladen wird, generiert die JVM ein Klassenobjekt dafür. Das Objekt, das wir im Programm instanziieren, ist tatsächlich Es wird zur Laufzeit basierend auf dem entsprechenden Klassenobjekt erstellt. Um genau zu sein, ist dieses Class-Objekt tatsächlich eine Instanz der generischen Klasse java.lang.Class> Das Class3a588aab6ae1f766128f21e776d37218-Objekt ist beispielsweise eine Class8742468051c85b06f0a0af9e3e506b5c-Instanz. Da die Klasse java.lang.Class8742468051c85b06f0a0af9e3e506b5c keinen öffentlichen Konstruktor hat, können wir diese Klasse nicht direkt instanziieren. Wir können ein Klassenobjekt über die folgende Methode erhalten.

In der folgenden Erklärung nehmen wir die People-Klasse und die Student-Klasse als Beispiele:

public class People {
      private String name;
      private int age;
      public People(String name, int age) {
          this.name = name;
              this.age = age;
      }
      public int getAge() {
          return age;
      } 
      public String getName() {
          return name;
      } 
      public void setAge(int age) {
          this.age = age;
      } 
      public void setName(String name) {
          this.name = name;
      }
      public void speak() {
        System.out.println(getName() + " " + getAge());
     }
}
 
public class Student extends People {
  private int grade;
  public Student(String name, int age) {    
    super(name, age);  
  }
  public Student(String name, int age, int grade) {
    super(name, age);            
    this.grade = grade;  
  }      
  public int getGrade() {   
    return grade;  
  }     
  public void setGrade(int grade) {   
    this.grade = grade;  
  }    
  private void learn(String course) {    
    System.out.println(name + " learn " + course);  
  }
}

Rufen Sie das Klassenobjekt über den Klassennamen ab

Wenn Sie eine Klasse kennen Zum Zeitpunkt der Kompilierung können wir das Klassenobjekt wie folgt abrufen:

Class<People> peopleClass = People.class;

Es gibt auch eine Methode, um das Klassenobjekt basierend auf dem vollständigen Pfadnamen der Klasse wie folgt abzurufen:

//假设People类在com.test包中
Class<People> peopleClass = Class.forName("com.test.People");

Beachten Sie, dass Class.forName() Der Methodenparameter muss der vollständige Pfadname einer Klasse sein. Solange wir „com.test.People“ importieren, können wir sein Klassenobjekt direkt über „People.class“ erhalten, ohne den vollständigen Pfad ausschreiben zu müssen. (Wenn die entsprechende Klasse beim Aufrufen der Class.forName()-Methode nicht im Klassenpfad gefunden wird, wird eine ClassNotFoundException ausgelöst.)

Rufen Sie ihr Klassenobjekt über das Objekt selbst ab

People people = new People("Bill", 18);
Class<People> peopleClass = people.getClass();

Rufen Sie das ab Klasse durch Reflexion Der Konstruktor von

Sobald wir das Klassenobjekt von Menschen erhalten, können wir über dieses Klassenobjekt die ursprünglichen Definitionsinformationen der Menschenklasse erhalten. Lassen Sie uns zunächst das Konstruktorobjekt der People-Klasse abrufen. Mit diesem Konstruktorobjekt können wir ein People-Objekt erstellen. Beispielsweise können wir den folgenden Code zu Student.java hinzufügen:

public static void main(String[] args) {   
  Class<People> pClass = People.class;   
  try {   
    Constructor<People> constructor = pClass.getConstructor(String.class, int.class);     
    People people = constructor.newInstance("Bill", 18);                 
    people.speak();  
  } catch (Exception e) {  
  } 
}

Oben rufen wir die getConstructor-Methode auf, um ein Konstruktorobjekt der People-Klasse zu erhalten. Da es sich um den formalen Parametertyp des Konstruktors handelt, den wir erhalten möchten ist String und int, also übergeben wir String.class und int.class. Mit dem Konstruktorobjekt können wir die Methode newInstance aufrufen, um ein Personenobjekt zu erstellen.

Beachten Sie, dass Sie nach dem Abrufen der Konstruktor-, Methoden- und Feldobjekte einer Klasse durch Reflektion vor dem Aufrufen der Methoden dieser Objekte zunächst das Accessible-Flag dieses Objekts auf true setzen, um die Java-Sprachzugriffsprüfung abzubrechen. Sie können die Reflexionsgeschwindigkeit erhöhen. Wie im folgenden Code gezeigt:

Constructor<People> constructor = peopleClass.getConstructor(String.class, 
    int.class);
// 设置 constructor 的 Accessible属性为ture以取消Java的访问检查
constructor.setAccessible(true);

Rufen Sie die in der Klasse deklarierten Methoden durch Reflektion ab

Rufen Sie die in der aktuellen Klasse deklarierten Methoden ab (mit Ausnahme derjenigen, die von der übergeordneten Klasse geerbt wurden)

Um alle in der aktuellen Klasse deklarierten Methoden abzurufen, können Sie die Funktion getDeclaredMethods in Class verwenden. Sie ruft alle in der aktuellen Klasse deklarierten Methoden ab (einschließlich privat, öffentlich, statisch usw.) und gibt eine zurück Array von Methodenobjekten, wobei jedes Methodenobjekt eine in einer Klasse deklarierte Methode darstellt. Um die angegebene Methode abzurufen, können Sie getDeclaredMethod(String name, Class...8742468051c85b06f0a0af9e3e506b5c parameterTypes) aufrufen. Wie im folgenden Code gezeigt:

private static void showDeclaredMethods() {  
  Student student = new Student("Bill", 18);   
  //获取Student类声明的所有方法 
  Method[] methods = student.getClass().getDeclaredMethods();       
   try {      
      //获取learnMethod对象(封装了learn方法) 
      Method learnMethod = student.getClass().getDeclaredMethod("learn", 
          String.class);                
      //获取learn方法的参数列表并打印出来 
      Class<?>[] paramClasses = learnMethod.getParameterTypes() ;        
      for (Class<?> class : paramClasses) {      
        System.out.println("learn方法的参数: " + class.getName());    
      }                
      //判断learn方法是否为private 
      System.out.println(learnMethod.getName() + " is private " 
          + Modifier.isPrivate(learnMethod.getModifiers()));   
      //调用learn方法    
      learnMethod.invoke(student, "Java Reflection");  
    } catch (Exception e) {  
  }
}

Rufen Sie die in der aktuellen Klasse und der übergeordneten Klasse deklarierten öffentlichen Methoden ab

Um alle in der aktuellen Klasse und der übergeordneten Klasse deklarierten öffentlichen Methoden abzurufen, müssen Sie Sie können die Funktion getMethods aufrufen. Um eine bestimmte öffentliche Methode zu erhalten, können Sie die Methode getMethod aufrufen. Bitte schauen Sie sich den folgenden Code an:

private static void showMethods() { 
  Student student = new Student("mr.simple");    
  // 获取所有public方法(包括Student本身的和从父类继承来的)  
  Method[] methods = student.getClass().getMethods();   
  try {    
    //注意,通过 getMethod只能获取public方法,若尝试获取private方法则会抛出异常 
    Method learnMethod = student.getClass().getMethod("learn", String.class);
  } catch (Exception e) {  
  }
}

Rufen Sie die in der Klasse definierten Attribute durch Reflektion ab

Das Abrufen von Attributen ähnelt dem Abrufen von Methoden, mit der Ausnahme, dass die Methoden getMethods() / getDeclaredMethods() aufgerufen werden werden ersetzt. Wird zu einem Aufruf der Methode getFields() / getDeclaredFields().

Rufen Sie die in der aktuellen Klasse definierten Attribute ab (mit Ausnahme der von der übergeordneten Klasse geerbten Attribute)

Um alle in der aktuellen Klasse definierten Attribute abzurufen (einschließlich privater, öffentlicher, statischer und anderer Attribute) Sie können die Funktion getDeclaredFields des Klassenobjekts aufrufen. Um die angegebenen Attribute abzurufen, können Sie getDeclaredField aufrufen. Wie im folgenden Code gezeigt:

private static void showDeclaredFields() {   
  Student student = new Student("Bill", 18);    
  // 获取当前类中定义的所有属性  
  Field[] fields = student.getClass().getDeclaredFields();   
  try {    
    // 获取指定的属性 
    Field gradeField = student.getClass().getDeclaredField("grade"); 
    // 获取属性值 
    System.out.println("The grade is : " + gradeField.getInt(student));    
    // 设置属性值    
    gradeField.set(student, 10); 
   } catch (Exception e) { 
  } 
}

Rufen Sie die in der aktuellen Klasse und der übergeordneten Klasse definierten öffentlichen Eigenschaften ab.

So rufen Sie alle in der aktuellen Klasse und der übergeordneten Klasse definierten öffentlichen Eigenschaften ab Sie können die getFields-Funktion des Klassenobjekts aufrufen. Um ein bestimmtes öffentliches Attribut abzurufen, können Sie die getField-Methode aufrufen, wie im folgenden Code gezeigt:

private static void showFields() {  
  Student student = new Student("Bill", 18);            
  // 获取当前类和父类的所有public属性 
  Field[] publicFields = student.getClass().getFields();        
}

Rufen Sie die übergeordnete Klasse der Klasse und die implementierte Schnittstelle ab durch die Klasse durch Reflexion

获取父类

调用Class对象的getSuperClass方法即可,如以下代码所示:

Student student = new Student("Bill", 18);
Class<?> superClass = student.getClass().getSuperclass();

获取所实现的接口

要知道一个类实现了哪些接口,只需调用Class对象的getInterfaces方法,如以下代码所示:

private static void showInterfaces() { 
  Student student = new Student("Bill", 19); 
  Class<?>[] interfaces = student.getClass().getInterfaces();
}

Das obige ist der detaillierte Inhalt vonSo verstehen Sie die Java-Reflexion. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn