Reflexión de Java: el alma del marco (bastante importante)

Prefacio

Continuando con el artículo anterior, acabo de terminar de aprender la reflexión recientemente y todavía hay algunas cosas que no son comprensibles, así que escribo un blog para enumerar el contenido que acabo de aprender. El contenido de este artículo son mis propias notas y las mías. comprensión. Hay algo mal. Me gustaría preguntarles a los grandes por el lugar.

El concepto de reflexión

Qué es la reflexión (Reflexión): Encapsula los diversos componentes de la clase como otros objetos, este es el mecanismo de reflexión. La reflexión como alma del marco se utiliza más en varios marcos.

Los beneficios de la reflexión

Estos objetos se pueden manipular durante la ejecución del programa, que se pueden desacoplar para mejorar la escalabilidad del programa. Por ejemplo, la reflexión se usa generalmente al cargar archivos de configuración de base de datos.

Comprensión dinámica del lenguaje

Java en sí es un lenguaje estático, pero la reflexión puede hacer que Java sea muy flexible.
El llamado lenguaje dinámico que personalmente entiendo es un lenguaje que puede cargar objetos durante la ejecución del programa.

Acerca de la clase

Tres formas de obtener objetos de clase

 public static void main(String[] args ) throws Exception{
    
    
        //创建Class对象的三种方式
        //1、通过Class.forName("全类名")
        Class c1 = Class.forName("cn.sjy.Person");
        System.out.println(c1);
        //2、通过 类名.class
        Class<Person> c2 = Person.class;
        System.out.println(c2);
        //3、 通过对象.getClass()
        Person person = new Person();
        System.out.println(person.getClass());
    }

El resultado se muestra en la figura:
Inserte la descripción de la imagen aquí
Se puede ver que los tres métodos obtienen un objeto Class. Cabe mencionar que el mismo archivo bytecode (archivo .class) solo se carga una vez durante la ejecución de un programa. Todos los tipos pueden tener objetos de clase, como propiedades, métodos, constructores, genéricos, anotaciones, etc.

Comprensión de la clase

La clase Class contiene toda la información de la clase, incluidos los métodos de construcción, propiedades, métodos, etc. La reflexión también se puede entender como un proceso en el que se devuelve un objeto Class después de que la clase Class se carga en la memoria y sus propios atributos de método se asignan a través de este objeto Class.

Carga de clases y comprensión de ClassLoader

Proceso de carga

El nombre de clase .class es un archivo de código de bytes. Necesitamos saber que un programa Java se ejecuta desde un archivo .java a un archivo .class, y luego carga el archivo .class en la memoria, es decir, coloca el archivo .class en el JVM Sólo cuando el archivo .class se coloca en la JVM puede ser multiplataforma. La función del ClassLoader es colocar el archivo .class en la JVM y cargarlo en un objeto Class (objeto java.lang.Class), y solo el objeto Class puede llamar a otros métodos.

ClassLoader (ClassLoader)

El cargador de clases es responsable de leer el archivo .class y convertirlo en una instancia de la clase java.lang.Class. Cada instancia se usa para representar una clase java. El método newInstance () de esta instancia puede crear la clase An objeto. A través de la reflexión, la clase es completamente transparente para nosotros. Independientemente de si eres privado o qué, podemos obtener lo que queramos a través de la reflexión. En términos generales, cuando una propiedad es privada, debemos llamar a los métodos get y set. Value y asignación, pero puede asignar y valorar atributos privados modificados directamente mediante la reflexión. Por supuesto, esto también tiene inconvenientes, ¡eso es lento! En comparación con un nuevo objeto para llamar a propiedades y métodos, ¡la reflexión es mucho más lenta!
Resumir el cargador de clases en una frase (comprensión personal): Después de obtener una instancia de Clase correspondiente a una clase, puede obtener toda la información de la clase.
El método de obtener información de clase a través de la instancia de clase se llama reflexión (Reflexión)

Función de objeto de clase y su instancia

Llamar objetos dinámicamente a través de la reflexión

El código es el mismo que el del blog anterior, aquí hay un resumen

 public static void main(String[] args ) throws Exception{
    
    
        //获取Class对象
        Class c1 = Class.forName("cn.sjy.Person");
        //实例化该对象,创建由此类对象表示的新的对象
        Person person = (Person) c1.newInstance();
        //newInstance()方法规定调用无参的构造函数
        System.out.println(person);

        //获得一个类的构造器
        Person person2 = (Person)c1.getConstructor(int.class, String.class).newInstance(2017021, "虎哥");
        //将这个类的构造器进行实例化
        System.out.println(person2);

        //调用一个普通方法
        Method fan = c1.getDeclaredMethod("fan");
        //需要忽略访问权限修饰符的安全检查--》暴力反射
        fan.setAccessible(true);
        fan.invoke(person);

        //操作属性
        Field id = c1.getDeclaredField("id");
        id.setAccessible(true);
        id.set(person,123);
        System.out.println(id.get(person));
    }
 public static void main(String[] args ) throws Exception {
    
    
        //获取Class对象,将这个字节码文件加载进内存
        Class c1 = Class.forName("cn.sjy.Person");
        //实例化这个Class对象,创建一个由此Class对象表示的新对象
            //newInstance()方法只能调用无参的构造函数
        Person person = (Person)c1.newInstance();

        //输出一个无参的构造函数
        System.out.println(person);
        //调用一个有参的构造函数,并且将其实例化
        Person p = (Person) c1.getConstructor(int.class, String.class).newInstance(2017021, "反射君");
        System.out.println(p);

        //调用属性,如果是public调用getField即可,但是如果是private需要调用getFDeclaredFeild方法
        Field id = c1.getDeclaredField("id");
        //关闭安全检查
        id.setAccessible(true);
        id.set(p,2017021);
        id.set(person,2017022);
        //输出这个属性的值
        System.out.println(id.get(person));
        System.out.println(id.get(p));

        //调用普通方法
        Method fan = c1.getDeclaredMethod("fan");
        fan.setAccessible(true);
        fan.invoke(p);
    }

Resultados del segundo fragmento de código:
Inserte la descripción de la imagen aquí

Clase de persona

package cn.sjy;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    
    
    public int id;
    private String name;

    /**普通方法*/
    private void fan(){
    
    
        System.out.println("通过反射来调用普通方法!");
    }
}

La clase My Person usa un complemento, a través de anotaciones puede obtener el método de construcción y similares.

Caso de reflexión en detalle

Llamar a un método común obteniendo información sobre un archivo de configuración

public static void main(String[] args ) throws Exception{
    
    
        //获取配置文件的位置
        File file = new File("D:\\JavaIDEA\\Test\\src\\pro.properties");
        //调用Properties类-->唯一一个和IO流结合的集合
            //Properties类实现了Map接口
        Properties pro = new Properties();
        //调用一个FileInputStream类读取一个文件
        FileInputStream fis = new FileInputStream(file);
        //读取这个文件的信息
        pro.load(fis);
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");
        //输出文件的信息
        System.out.println(className);
        System.out.println(methodName);

        //根据配置文件的值创建Class对象
        Class c1 = Class.forName(className);

        //调用Person的普通方法
        Method fan = c1.getDeclaredMethod("fan");
        //因为该普通方法是private修饰的所以需要关闭检测
        fan.setAccessible(true);
        //执行该方法
        fan.invoke(c1.newInstance());
    }

El resultado se muestra en la figura (esta clase Person y las anteriores son una clase):
Inserte la descripción de la imagen aquí
A continuación, hablemos en detalle sobre la función de cada paso.
Class.forName ("nombre de clase completo"): Cargue esta clase en la memoria mediante el nombre completo de la clase y luego crear una instancia para generar un objeto Class.
.newInstance (): instancia este objeto Class, otra forma es llamar al constructor sin parámetros de este objeto, preste atención al constructor sin parámetros, newInstance () llama al constructor sin parámetros de forma predeterminada, si desea llamar El constructor parametrizado debe ser implementado usando getConstractor (Object.class, Object.class ...). newInstance (obj.obj ...).
Nota: El bloque de código {} estático se ejecuta antes de la inicialización de la clase, por lo que el bloque de código {} estático se usa generalmente para cargar archivos de configuración y otra información.
Referencia activa de la clase (definitivamente ocurrirá la inicialización de la clase), reflexión, un nuevo objeto
Referencia pasiva de la clase (no ocurrirá la inicialización de la clase), subclase, variable de clase padre, matriz

para resumir

He aprendido algunos conocimientos sobre la reflexión de Java en la actualidad. Lo he aprendido muy superficialmente, pero no lo he hecho en profundidad. Planeo profundizar más cuando entre en contacto con el marco en el futuro. A continuación, resolveré el contenido sobre subprocesos múltiples. La capacidad es limitada, así que tengan paciencia. Solo salsa ~

Supongo que te gusta

Origin blog.csdn.net/weixin_44475741/article/details/109450921
Recomendado
Clasificación