Maison  >  Article  >  Java  >  Comment comprendre la réflexion Java

Comment comprendre la réflexion Java

藏色散人
藏色散人original
2019-11-13 10:19:372847parcourir

Comment comprendre la réflexion Java

Comment comprendre la réflexion Java ?

Vue d'ensemble

La réflexion Java est un mécanisme qui nous permet d'obtenir des informations internes sur les classes telles que les méthodes, les propriétés, les classes parents, les interfaces, etc. exécution. En d’autres termes, la réflexion est essentiellement un processus « inverse ». Lorsque nous créons une instance d'une classe via new, elle est en fait construite par la machine virtuelle Java au moment de l'exécution sur la base de l'objet Class de cette classe, et la réflexion obtient ses informations de définition via l'objet Class d'une classe, afin que nous puissions accéder Accédez à ses attributs et méthodes, connaissez la classe parent de cette classe, quelles interfaces sont implémentées et d'autres informations.

Classe de classe

Nous savons que javac peut être utilisé pour compiler des fichiers .java en fichiers .class Ce fichier .class contient nos informations de définition originales de la classe (. classes parents, interfaces, constructeurs, propriétés, méthodes, etc.). Le fichier .class sera chargé dans la machine virtuelle Java (JVM) par le ClassLoader au moment de l'exécution. Lorsqu'un fichier .class est chargé, la JVM générera un objet Class pour celui-ci. L'objet que nous instancions via new dans le programme est en fait. Il est construit sur la base de l'objet Class correspondant au moment de l'exécution. Pour être précis, cet objet Class est en fait une instance de la classe générique java.lang.Class8742468051c85b06f0a0af9e3e506b5c. Par exemple, l'objet Class3a588aab6ae1f766128f21e776d37218 est une instance Class8742468051c85b06f0a0af9e3e506b5c Étant donné que la classe java.lang.Class8742468051c85b06f0a0af9e3e506b5c n'a pas de constructeur public, nous ne pouvons pas instancier cette classe directement. Nous pouvons obtenir un objet Class via la méthode suivante.

Dans l'explication suivante, nous prendrons comme exemples la classe People et la classe Student :

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);  
  }
}

Récupérez l'objet Class via le nom de la classe

Si vous connaissez une classe au moment de la compilation Name, nous pouvons obtenir son objet Class comme ceci :

Class<People> peopleClass = People.class;

Il existe également une méthode pour obtenir l'objet Class en fonction du nom de chemin complet de la classe comme suit :

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

Notez que Class.forName() Le paramètre de méthode doit être le chemin d'accès complet d'une classe. En fait, tant que nous "importons com.test.People", nous pouvons obtenir directement son objet Class via "People.class" sans avoir à écrire le chemin complet. (Si la classe correspondante n'est pas trouvée sur le chemin de classe lors de l'appel de la méthode Class.forName(), ClassNotFoundException sera levée.)

Obtenez son objet Class via l'objet lui-même

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

Obtenez le la classe par réflexion Le constructeur de

Une fois que nous avons obtenu l'objet Class de People, nous pouvons obtenir les informations de définition originales de la classe People via cet objet Class. Tout d’abord, récupérons l’objet constructeur de la classe People. Avec cet objet constructeur, nous pouvons construire un objet People. Par exemple, nous pouvons ajouter le code suivant à Student.java :

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) {  
  } 
}

Ci-dessus, nous appelons la méthode getConstructor pour obtenir un objet constructeur de la classe People Depuis le type de paramètre formel du constructeur que nous voulons obtenir. est String et int, nous passons donc String.class et int.class. Avec l'objet constructeur, nous pouvons appeler la méthode newInstance pour créer un objet people.

Notez qu'après avoir obtenu les objets Constructor, Method et Field d'une classe par réflexion, avant d'appeler les méthodes de ces objets, définissez d'abord l'indicateur accessible de cet objet sur true pour annuler la vérification d'accès au langage Java. Vous pouvez augmenter la vitesse de réflexion. Comme indiqué dans le code suivant :

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

Récupérer les méthodes déclarées dans la classe par réflexion

Récupérer les méthodes déclarées dans la classe actuelle (hors celles héritées de la classe parent)

Pour obtenir toutes les méthodes déclarées dans la classe actuelle, vous pouvez utiliser la fonction getDeclaredMethods dans Class. Elle obtiendra toutes les méthodes déclarées dans la classe actuelle (y compris privée, publique, statique, etc.), et renverra un tableau d’objets Method, où chaque objet Method représente une méthode déclarée dans une classe. Pour obtenir la méthode spécifiée, vous pouvez appeler getDeclaredMethod(String name, Class...8742468051c85b06f0a0af9e3e506b5c ParameterTypes). Comme indiqué dans le code suivant :

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) {  
  }
}

Récupérez les méthodes publiques déclarées dans la classe actuelle et la classe parent

Pour obtenir toutes les méthodes publiques déclarées dans la classe actuelle et la classe parent, vous peut appeler la fonction getMethods, et pour obtenir une méthode publique spécifiée, vous pouvez appeler la méthode getMethod. Veuillez regarder le code suivant :

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) {  
  }
}

Obtenir les attributs définis dans la classe par réflexion

Obtenir des attributs est similaire à obtenir des méthodes, sauf que les appels aux méthodes getMethods() / getDeclaredMethods() sont remplacés Devient un appel à la méthode getFields() / getDeclaredFields().

Récupérer les attributs définis dans la classe actuelle (hors attributs hérités de la classe parent)

Pour obtenir tous les attributs définis dans la classe actuelle (y compris les attributs privés, publics, statiques et autres) Vous pouvez appeler la fonction getDeclaredFields de l'objet Class ; pour obtenir les attributs spécifiés, vous pouvez appeler getDeclaredField. Comme indiqué dans le code suivant :

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) { 
  } 
}

Obtenir les propriétés publiques définies dans la classe actuelle et la classe parent

Pour obtenir toutes les propriétés publiques définies dans la classe actuelle et la classe parent, vous peut appeler la fonction getFields de l'objet Class , et pour obtenir un attribut public spécifié, vous pouvez appeler la méthode getField, comme indiqué dans le code suivant :

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

Obtenir la classe parent de la classe et l'interface implémentée par la classe par la réflexion

获取父类

调用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();
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn