Dominar Java Reflection: consejos y trucos para desarrolladores avanzados

1. Definición de reflexión

La definición de reflexión: el mecanismo de reflexión de Java es que en el estado de ejecución, para cualquier clase, puede conocer todas las propiedades y métodos de esta clase, para cualquier objeto, puede llamar a cualquiera de sus métodos y propiedades. , entonces podemos modificar parte de la información del tipo. Esta función de obtener información de forma dinámica y llamar a métodos de objetos de forma dinámica se denomina mecanismo de reflexión.

El mecanismo de reflexión simplemente significa que cualquier método y propiedad en una clase u objeto (ya sea público o privado modificado) se puede obtener en el estado de ejecución.

Por ejemplo: Suponiendo que una universidad comienza la escuela, los estudiantes universitarios tienen que tomar varios medios de transporte para llegar a la escuela durante el período en que comienza la escuela.Algunos estudiantes irán a la escuela en avión, tren o autobús.Los estudiantes que usan las herramientas primero deben pasar por el control de seguridad en la estación correspondiente antes de que puedan abordar el medio de transporte correspondiente. Luego, al pasar el control de seguridad, deben colocar la maleta y las cosas que llevan en la máquina de control de seguridad para escanear. Al escanear , pueden pasar el correspondiente El dispositivo ve si hay artículos prohibidos en la maleta y artículos de mano

2. El propósito de la reflexión

  • Cuando algunas propiedades y métodos en una clase son privados o solo están abiertos a aplicaciones del sistema, se puede usar la reflexión para obtener las propiedades y métodos privados requeridos.

  • El uso más importante de la reflexión es desarrollar varios marcos generales

3. Clases importantes relacionadas con la reflexión

nombre de la clase

usar

clase de clase

Una entidad que representa una clase, que representa clases e interfaces en una aplicación Java en ejecución

clase de campo

Representa las variables miembro de la clase/atributos de la clase

clase de método

método de la clase delegada

Clase de constructor

Constructor de clase delegada

4. El origen del mecanismo de reflexión: la clase Class

Clase representa la entidad de una clase y representa clases e interfaces en una aplicación Java en ejecución

Después de compilar el archivo Java, generará un archivo .class, y la JVM interpretará el archivo .class en este momento.La JVM también analiza el archivo Java compilado .class en un objeto, y este objeto es java. lang.class. Cuando el programa se está ejecutando, cada archivo java eventualmente se convierte en una instancia del objeto de clase Class. Podemos aplicarlo a esta instancia a través del mecanismo de reflexión de Java para obtener o incluso agregar y cambiar los atributos y acciones de esta clase, haciendo de esta clase una clase dinámica.

5. Métodos relacionados de la clase Class

Métodos comúnmente utilizados para obtener clases.

方法

用途

getClassLoader()

获得类的加载器

getDeclareClasses()

返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)

forName(String classNme)

根据类名返回类的对象

newInstance()

创建类的实例

getName()

获得类的完整路径名字

常用获得类中属性相关的方法(以下方法返回值为Field)

方法

用途

getField(String name)

获得某个公有的属性对象

getFields()

获得所有公有的属性对象

getDeclaredField(String name)

获得某个属性对象

getDeclaredFields()

获得所有属性对象

获得类中注解相关的方法

方法

用途

getAnnotation(Class annotationClass)

返回该类中与参数类型匹配的公有注解对象

getAnnotations()

返回该类所有的公有注解对象

getDeclaredAnnotation(Class annotationClass)

返回该类中与参数类型匹配的所有注解对象

getDeclaredAnnotations()

返回该类所有的注解对象

获得类中方法相关的方法 (以下方法返回值为Method 相关)

方法

用途

getMethod(String name,Class...<?> parameterTypes)

获得该类某个公有方法

getMethod()

获得该类所有公有的方法

getDeclaredMethod(String name,Class...<?> parameterTypes)

获得该类某个方法

getDeclaredMethod()

获得该类所有方法

获得类中构造器相关的方法(以下方法返回值为Constructor相关)

方法

用途

getConstructor(Class...<?> parameterTypes )

获得该类中与参数类型匹配的公有构造方法

getConstructors()

获得该类的所有公有构造方法

getDeclaredConstructor(Class...<?> parameterTypes)

获得该类中与参数类型匹配的构造方法

getDeclaredConstructors()

获得该类所有构造方法

6、 获得 Class 对象

我们想要进行反射,首先得拿到需要反射类的Class对象,通过 Class 对象的核心方法,来进行反射。

获得Class对象分别有三种方法:

  • 使用类对象的 getClass() 方法

  • 使用 .class 方法,仅时候在编译前就已经明确要操作的Class

  • 使用Class.forName("类得全路径名"),这个forName是Class这个类的静态方法,这个获取Class对象的前提条件就是知道类的全路径名

示例:

public class Student {
    private String name = "张三";//私有属性
    public int age = 18;//公共属性
    //不带参数的构造方法
    public Student(){
        System.out.println("Student()");
    }
    //带参数的私有构造方法
    private Student(String name,int age) {
        this.name = name;
        this.age = age;
        System.out.println("Student(String,name)");
    }
    //私有方法
    private void eat(){
        System.out.println("i am eat");
    }
    //公共方法
    public void sleep(){
        System.out.println("i am sleep");
    }
    //带有参数的私有方法
    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

现在我们就通过获取 Class 对象的三种方法,分别来获取上述的 Student 类的 Class 对象

使用类对象的 getClass() 方法获取:

public static void main(String[] args) {
        Student student = new Student();
        Class<?> s1 = student.getClass();
    }

使用 .class 方法获取:

直接通过 类名.class 的方式获得到的Class对象的方法最为安全可靠,程序性能也会更高,直接通过 类型.class 的方式获得到,也就说明任何一个类都有一个隐含的静态成员变量class

public static void main(String[] args) {
        Class<?> s2 = Student.class;
    }

使用Class.forName("类得全路径名") 方法获取:

通过 Class 对象的 forName() 静态方法来获取,可能会抛出 ClassNotFoundException 异常

public static void main(String[] args) {
        Class<?> s3 = null;
        try {
            s3 = Class.forName("Student");//这里是类的全路径,如果有包需要加包的路径
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

注意:一个类在 JVM中只会有一个 Class 实例,那么也就是说上面我们获取的 s1、s2、s3 这些 Class 对象,其实都是一个 Class 对象

System.out.println(s1.equals(s2));
System.out.println(s1.equals(s3));
System.out.println(s2.equals(s3));

打印结果:

7、 反射的使用

我们目前已经知道了如何获取到一个类的Class实例,那么接下来我们就通过 Class 实例来进行反射的使用

我们还是使用上述的 Student 类来进行反射的使用

7.1 通过反射创建一个 Student 对象

1、通过公共构造方法创建对象

public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        Class<?> studentClass = Student.class;//获取类的Class实例
        Object objectStudent = studentClass.newInstance();//通过Class实例,创建一个对象
        Student student = (Student) objectStudent;
        System.out.println("获得的学生对象:"+student);
    }

2、通过私有构造方法创建对象

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class<?> studentClass = Student.class;
        Constructor<?> declaredConstructorStudent = studentClass.getDeclaredConstructor(String.class,int.class);
        declaredConstructorStudent.setAccessible(true);//设置为true后可修改访问权限
        Object objectStudent = declaredConstructorStudent.newInstance("李四",18);
        Student student = (Student)objectStudent;
        System.out.println(student);
    }

7.2 通过反射获取私有属性

public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException {
        Class<?> studentClass = Student.class;
        Field field = studentClass.getDeclaredField("name");
        field.setAccessible(true);
        Object objectStudent = studentClass.newInstance();
        Student student = (Student)objectStudent;
        String name = (String) field.get(student);
        System.out.println(name);
    }

7.3 通过反射获取私有方法

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        Class<?> studentClass = Student.class;
        Method method = studentClass.getDeclaredMethod("function",String.class);
        System.out.println("私有方法的方法名:"+method.getName());
        method.setAccessible(true);
        Object objectStudent = studentClass.newInstance();
        Student student = (Student)objectStudent;
        method.invoke(student,"私有方法的参数");
    }

注:反射机制不能反射枚举

Supongo que te gusta

Origin blog.csdn.net/m0_66488562/article/details/128924743
Recomendado
Clasificación