[Aprendiendo JAVA desde cero | Artículo 45] Reflexión

Tabla de contenido

Prefacio:

Reflexión:

 Pasos para usar la reflexión:

1. Etapa de adquisición:

2. Etapa de uso:

Escenarios de aplicación de la reflexión:

Pros y contras de usar la reflexión:

Resumir:


Prefacio:

Reflection en Java es una función poderosa y flexible que permite que los programas obtengan, manipulen y utilicen dinámicamente información de clase en tiempo de ejecución . A través de la reflexión, podemos inspeccionar y modificar las propiedades de la clase, llamar a los métodos de la clase e incluso crear y manipular instancias de objetos en tiempo de ejecución. Esta capacidad proporciona a Java mucha flexibilidad y extensibilidad, lo que nos permite escribir código más genérico, conectable y dinámico. Sin embargo, la reflexión también es una característica avanzada y debe usarse con precaución, ya que puede sacrificar algo de rendimiento y seguridad de tipos. En este artículo, profundizaremos en los principios, el uso y las mejores prácticas de la reflexión de Java.

reflexión:

                La reflexión es la capacidad de obtener, inspeccionar y manipular dinámicamente información sobre una clase en tiempo de ejecución . Permite que un programa obtenga la estructura completa de una clase por su nombre en tiempo de ejecución y puede instanciar objetos, llamar a métodos, acceder a propiedades y realizar otras operaciones relacionadas con la clase sin hacer referencia explícita a esas clases en tiempo de compilación. El núcleo de la reflexión es el paquete java.lang.reflect , que proporciona un conjunto de clases e interfaces para implementar funciones de reflexión. Usando la reflexión, se pueden implementar algunas técnicas de programación flexibles y generales, como la carga dinámica de clases, el análisis de archivos de configuración, la extensión del marco y la generación de código. Sin embargo, la reflexión también genera una sobrecarga de rendimiento y rompe la verificación de tipos en tiempo de compilación , por lo que debe prestar atención a la moderación y la racionalidad al usarla.

Es decir: la reflexión puede sacar las variables miembro, los métodos miembro y los métodos de construcción en la clase por separado para acceder ¿Nos preguntamos por qué la idea tiene una función de solicitud después de personalizar la clase?

De hecho, esto se logra  a través de la reflexión .

 Pasos para usar la reflexión:

1. Etapa de adquisición:

En la fase de adquisición, utilizamos el mecanismo de reflexión para obtener información relacionada con clases, métodos, campos, etc. Esto incluye obtener el objeto Class , el método de construcción , el método , el campo , etc. de la clase y verificar la información de los metadatos, como la relación de herencia, la implementación de la interfaz y las anotaciones de la clase. La fase de adquisición brinda la capacidad de explorar y analizar la estructura de la clase, permitiéndonos obtener dinámicamente la información estructural de la clase.

(1) Use la reflexión para obtener el objeto de clase

public class test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //获取class文件:
        //第一种
        Class<?> aClass = Class.forName("Myrflect.student");
        System.out.println(aClass);

        //第二种:
        Class<student> studentClass = student.class;
        System.out.println(studentClass);

        //第三种:
        student st = new student();
        Class<? extends student> aClass1 = st.getClass();
        System.out.println(aClass1);

    }
}

(2) Usar la reflexión para obtener el método de construcción

public class getcontrbute {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        //1.获取字节码文件对象
        Class<?> aClass = Class.forName("Myrflect.student");
        
        //1.获取公共的构造方法:
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("-------------------------");
        
        //2.获取私有的构造方法
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> cons : declaredConstructors) {
            System.out.println(cons);
        }
        System.out.println("-------------------------");
        
        //3.获取单个的构造方法
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        System.out.println(declaredConstructor);
        Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(String.class,int.class,String.class);
        System.out.println(declaredConstructor1);
        
    }
}

(3) Reflexión para obtener variables miembro

public class getmember {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        //1.获取Class字节码文件对象
        Class<?> aClass = Class.forName("Myrflect.student");

        //1.获取所有公告成员变量对象的数组
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("---------------");
        //2.获取所有成员变量对象的数组
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field field : declaredFields) {
            System.out.println(field);
        }
        System.out.println("---------------");
        //3.获取单个成员变量
        Field name = aClass.getField("name");
        System.out.println(name);
    }
}

 (4) Reflexión para obtener métodos miembro

public class getway {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        Class<?> aClass = Class.forName("Myrflect.student");

        //1.获取所有公共方法对象(包含父类,而每一个类都继承Object类,因此打印会出现很多方法)
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("-----------------------------");
        //2.获取所有方法对象(不包含父类)
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method method : declaredMethods) {
            System.out.println(method);
        }
        System.out.println("-----------------------------");
        //3.获取单个方法
        Method method = aClass.getMethod("getAge");
        System.out.println(method);

    }
}

2. Etapa de uso:

Después de obtener la información estructural de la clase, podemos usar el mecanismo de reflexión para crear instancias dinámicamente de objetos, métodos de llamada, campos de acceso y otras operaciones. La etapa de uso utiliza la información obtenida en la etapa de adquisición para operar a los miembros de la clase a través de la reflexión para lograr funciones flexibles, generales y dinámicas. La etapa de uso puede manipular dinámicamente los miembros de la clase de acuerdo con las necesidades reales, sin necesidad de determinar las clases y los miembros específicos por adelantado en el momento de la compilación.

public class ReflectionExample {
    public static void main(String[] args) {
        try {
            // 读取和写入字段
            MyClass obj = new MyClass();
            Class<?> clazz = obj.getClass();
            
            // 获取公共字段
            Field publicField = clazz.getField("publicField");
            System.out.println("Public Field Initial Value: " + publicField.get(obj));
            
            // 设置字段的值
            publicField.set(obj, "New Value");
            System.out.println("Public Field Updated Value: " + publicField.get(obj));
            
            // 获取私有字段
            Field privateField = clazz.getDeclaredField("privateField");
            privateField.setAccessible(true); // 设置私有字段可访问
            System.out.println("Private Field Initial Value: " + privateField.get(obj));
            
            // 设置私有字段的值
            privateField.set(obj, 123);
            System.out.println("Private Field Updated Value: " + privateField.get(obj));
            
            // 调用方法
            Method method = clazz.getMethod("publicMethod");
            method.invoke(obj); // 执行公共方法
            
            // 创建对象
            Constructor<?> constructor = clazz.getConstructor();
            Object newObj = constructor.newInstance();
            System.out.println("New Object: " + newObj);
        } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}

Reflection también proporciona muchas otras funciones, como obtener constructores de clases, interfaces, clases principales, obtener información de anotaciones, etc.

Cabe señalar que cuando se utiliza la reflexión, se debe prestar atención a las restricciones de permisos (como el acceso a miembros privados) y los problemas de rendimiento (las operaciones de reflexión tienen menos rendimiento que las llamadas directas). Además, el uso de la reflexión debe seguir los principios de diseño tanto como sea posible, evitar el abuso de la reflexión y garantizar la legibilidad y el mantenimiento del código.

Escenarios de aplicación de la reflexión:

  1. Desarrollo de marcos : la reflexión se usa a menudo en el desarrollo de marcos para cargar dinámicamente clases, crear objetos, llamar a métodos y acceder a campos mediante la lectura de archivos de configuración o anotaciones, logrando así una estructura de marco flexible y extensible.

  2. Creación de instancias de objetos : las instancias de objetos se pueden crear dinámicamente a través de la reflexión. A través del objeto de la claseConstructor, se pueden llamar a diferentes constructores y se pueden pasar diferentes parámetros al objeto, para crear el objeto de acuerdo con las necesidades.

  3. Llamar a métodos y acceder a campos : Reflection se puede usar para llamar a métodos de una clase y acceder a campos de una clase. Los objetos a través de métodosMethodpueden llamar a diferentes métodos de la clase, yFieldlos objetos a través de campos pueden leer y escribir valores de campo de la clase.

  4. Explore la información de la clase : a través de la reflexión, puede obtener información detallada sobre una clase, como el nombre de la clase, la clase principal, la interfaz, el método y el campo. Esto es útil para escribir código genérico y hacer cosas como la generación, serialización y validación de documentos.

  5. Proxies dinámicos : la reflexión juega un papel importante en la implementación de proxies dinámicos. La clase de proxy se puede generar dinámicamente a través de la reflexión, y se puede agregar lógica adicional a la llamada al método de la clase de proxy, como registro, verificación de autorización, etc.

  6. Pruebas unitarias : la reflexión se puede usar para objetos simulados al escribir pruebas unitarias. Reflection le permite crear objetos falsos y simular el comportamiento de objetos reales para realizar pruebas unitarias más completas.

Pros y contras de usar la reflexión:

ventaja:

  1. Dinámica : Reflection proporciona la capacidad de obtener y manipular dinámicamente clases en tiempo de ejecución. Se pueden crear objetos, invocar métodos y acceder a campos de forma dinámica, lo que hace que el código sea más flexible y extensible.

  2. Versatilidad : el código genérico se puede escribir a través de la reflexión, independientemente de las clases e interfaces específicas. Puede obtener información de la clase sin conocer la estructura de la clase y manipular los miembros de la clase según sea necesario.

  3. Compatibilidad con marcos : Reflection se usa ampliamente en el desarrollo de marcos. Los marcos pueden cargar clases dinámicamente y crear objetos mediante la lectura de archivos de configuración o anotaciones, logrando así una estructura de marco flexible y configurable.

  4. Flexibilidad : Reflection hace posible seleccionar y ejecutar código dinámicamente en función de las condiciones en tiempo de ejecución, en lugar de un enlace estático en tiempo de compilación. Esto es muy útil en ciertos escenarios comerciales específicos. Por ejemplo, seleccione dinámicamente diferentes clases de implementación en función de los archivos de configuración.

defecto:

  1. Sobrecarga de rendimiento : la reflexión es generalmente más lenta que llamar directamente al código porque requiere búsquedas, comprobaciones y llamadas adicionales. La sobrecarga de rendimiento de las llamadas reflexivas es relativamente alta y las aplicaciones que pueden ser sensibles al rendimiento deben usarse con precaución.

  2. Problemas de seguridad : el uso de la reflexión puede eludir el control de acceso y el mecanismo de verificación de seguridad de la clase, lo que puede generar brechas de seguridad. Por lo tanto, al usar la reflexión, debe mantener su código seguro y asegurarse de que solo el código confiable pueda acceder a operaciones confidenciales.

  3. Faltan verificaciones del compilador : Reflection puede hacer que el código sea más dinámico, pero también pierde la capacidad del compilador para realizar la verificación de errores durante la fase de compilación del código. Es posible que algunos errores no se descubran hasta el tiempo de ejecución, lo que dificulta la depuración.

Resumir:

Reflection es una característica poderosa en Java, a través de la cual podemos obtener y manipular dinámicamente miembros de una clase en tiempo de ejecución. La flexibilidad, la versatilidad y el dinamismo se pueden lograr mediante la reflexión, proporcionando funciones como la creación de objetos, métodos de llamada y campos de acceso. Sin embargo, la reflexión también tiene algunas desventajas, como la sobrecarga de rendimiento y los problemas de seguridad. Por lo tanto, se deben hacer concesiones al usar la reflexión, asegurándose de que sea seguro de usar y siguiendo las mejores prácticas. En resumen, la reflexión proporciona a los programas Java una mayor flexibilidad y escalabilidad, lo que hace que la escritura de código sea más versátil y adaptable a las necesidades que cambian dinámicamente.

Si mi contenido es útil para ti, dale me gusta, comenta y marca . ¡La creación no es fácil, el apoyo de todos es mi motivación para perseverar!

 

Supongo que te gusta

Origin blog.csdn.net/fckbb/article/details/132206812
Recomendado
Clasificación