Try using it in your preferred language.

English

  • English
  • 汉语
  • Español
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar
translation

Esta es una publicación traducida por IA.

제이온

[Java] Concepto y uso de la reflexión

Seleccionar idioma

  • Español
  • English
  • 汉语
  • Bahasa Indonesia
  • Português
  • Русский
  • 日本語
  • 한국어
  • Deutsch
  • Français
  • Italiano
  • Türkçe
  • Tiếng Việt
  • ไทย
  • Polski
  • Nederlands
  • हिन्दी
  • Magyar

Texto resumido por la IA durumis

  • La reflexión es una API que le permite acceder a la información de clase en tiempo de ejecución y manipular la clase a su gusto.
  • A través de la reflexión, puede crear instancias de clases y acceder a campos y métodos independientemente de los modificadores de acceso, y es útil para administrar dinámicamente las dependencias en grandes etapas de desarrollo como los marcos.
  • Sin embargo, dado que puede violar la encapsulación y causar una disminución del rendimiento, es mejor usarlo solo cuando sea necesario.

¿Qué es Reflection?

Reflection es una API que admite la creación de instancias de una clase deseada a través de un objeto de tipo Class cargado en el área de montón, y permite acceder a los campos y métodos de la instancia independientemente de los modificadores de acceso.



Aquí, la clase cargada significa que el cargador de clase JVM ha completado la carga del archivo de clase y luego ha creado un objeto de tipo Classque contiene la información de esa clase y la ha almacenado en el área de montón de la memoria. Tenga en cuenta que es diferente de los objetos creados mediante la palabra clave new. Si no está familiarizado con este objeto de tipo Class, consulte la documentación de JDK para java.lang.class.


Cómo usarlo

Antes de usar la reflexión, debe obtener el objeto de tipo Class que está cargado en el área de montón. Hay un total de 3 métodos.


  • Obtener mediante class.class
  • Obtener mediante instance.getClass()
  • Obtener mediante Class.forName("nombre de la clase")


public class Member {

    private String name;

    protected int age;

    public String hobby;

    public Member() {
    }

    public Member(String name, int age, String hobby) {
        this.name = name;
        this.age = age;
        this.hobby = hobby;
    }

    public void speak(String message) {
        System.out.println(message);
    }

    private void secret() {
        System.out.println("La contraseña es 1234.");
    }

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

public class Main {

    public static void main(String[] args) throws ClassNotFoundException {
        Class memberClass = Member.class;
        System.out.println(System.identityHashCode(memberClass));

        Member member = new Member("Jayon", 23, "Desarrollo de Darath");
        Class memberClass2 = member.getClass();
        System.out.println(System.identityHashCode(memberClass2));

        Class memberClass3 = Class.forName("{nombre del paquete}.Member");
        System.out.println(System.identityHashCode(memberClass3));
    }
}

// Resultados de la ejecución
1740000325
1740000325

Puede ver que las instancias de tipo Class obtenidas mediante los tres métodos son las mismas. No importa qué método use, el valor hash es el mismo, así que puede usarlo según sea necesario.


Ahora, puede crear una instancia de la clase utilizando el tipo Class obtenido y también puede acceder a los campos y métodos de la instancia independientemente de los modificadores de acceso. Primero, cree una instancia de la clase.


public class Main {

    public static void main(String[] args) throws Exception {
        // Imprimir todos los constructores de Member
        Member member = new Member();
        Class memberClass = member.getClass();
        Arrays.stream(memberClass.getConstructors()).forEach(System.out::println);

        // Creación de instancia mediante el constructor predeterminado de Member
        Constructor constructor = memberClass.getConstructor();
        Member member2 = constructor.newInstance();
        System.out.println("member2 = " + member2);

        // Creación de instancia mediante otro constructor de Member
        Constructor fullConstructor =
            memberClass.getConstructor(String.class, int.class, String.class);
        Member member3 = fullConstructor.newInstance("Jayon", 23, "Desarrollo de Darath");
        System.out.println("member3 = " + member3);
    }
}

// Resultados de la ejecución
public Member()
public Member(java.lang.String,int,java.lang.String)
member2 = Member{name='null', age=0, hobby='null'}

Puede obtener el constructor mediante getConstructor() y crear dinámicamente una instancia de Member mediante newInstance().

Finalmente, acceda a los campos y métodos de la instancia independientemente de los modificadores de acceso.

public class Main {

    public static void main(String[] args) throws Exception {
        Member member = new Member("Jayon", 23, "Desarrollo de Darath");
        Class memberClass = member.getClass();

        // Acceso al campo
        Field[] fields = memberClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            System.out.println(field.get(member));
        }
        fields[0].set(member, "Jayon2");
        System.out.println(member);

        // Acceso al método
        Method speakMethod = memberClass.getDeclaredMethod("speak", String.class);
        speakMethod.invoke(member, "Prueba de Reflection");

        Method secretMethod = memberClass.getDeclaredMethod("secret");
        secretMethod.setAccessible(true);
        secretMethod.invoke(member);
    }
}

// Resultados de la ejecución
Jayon
23
Desarrollo de Darath
Member{name='Jayon2', age=23, hobby='Desarrollo de Darath'}
Prueba de Reflection

Puede obtener todas las variables de instancia de la clase mediante getDeclaredFileds(), puede obtener el valor del campo mediante get() y puede modificar el valor del campo mediante set(). Tenga en cuenta que cuando accede a un campo que tiene un modificador de acceso privado, debe pasar true al argumento de setAccessible().


Los métodos también se pueden obtener mediante getDeclaredMethod(). En este caso, debe pasar el nombre del método y el tipo de parámetro como argumentos. De manera similar, debe establecer el argumento de setAccessible() en true cuando acceda a un método que tiene un modificador de acceso privado. Finalmente, puede llamar al método obtenido mediante la API de Reflection mediante el método invoke().


Ventajas y desventajas

  • Ventajas
    • Tiene la flexibilidad de crear instancias de una clase en tiempo de ejecución y acceder a los campos y métodos independientemente de los modificadores de acceso para realizar las tareas necesarias.
  • Desventajas
    • Viola la encapsulación.
    • No se puede verificar el tipo en tiempo de compilación porque la instancia se crea en tiempo de ejecución.
    • Es difícil comprender el flujo de trabajo específico porque la instancia se crea en tiempo de ejecución.
    • El rendimiento es más lento al usar la reflexión para acceder a los campos y métodos que al acceder directamente. (No siempre es más lento).


Razón para usar

Puede acceder a la información de la clase en tiempo de ejecución mediante la API de Reflection para manipular la clase a su gusto. Incluso puede manipular campos y métodos declarados con un modificador de acceso privado. Puede parecer que no debe usarse porque rompe la encapsulación, que es importante en el diseño orientado a objetos.


En el nivel de consola de escala pequeña, el desarrollador puede comprender completamente los objetos que se utilizarán en el programa y las relaciones de dependencia en tiempo de compilación. Sin embargo, es difícil comprender la gran cantidad de objetos y relaciones de dependencia en las etapas de desarrollo de gran escala, como los marcos. En este caso, la reflexión se puede utilizar para crear clases dinámicamente y establecer relaciones de dependencia.


Por ejemplo, si mira Bean Factory de Spring, puede ver que solo necesita adjuntar anotaciones como @Controller, @Service y @Repository, y Bean Factory creará y administrará automáticamente la clase a la que se adjunta la anotación. El desarrollador no ha informado a Bean Factory sobre esa clase, pero esto es posible debido a la reflexión. Si encuentra una clase a la que se adjunta esa anotación en tiempo de ejecución, se usa para crear una instancia de esa clase mediante la reflexión, inyectar los campos necesarios y almacenarla en Bean Factory.


Por supuesto, como se mencionó anteriormente, viola la encapsulación, por lo que es mejor usarlo solo cuando sea necesario.


Fuente

제이온
제이온
제이온
제이온
[Effective Java] Item 2. Considere un constructor si el constructor tiene muchos parámetros Al crear objetos con muchos parámetros, el uso del patrón de constructor puede hacer que el código sea más limpio y fácil de leer. Cree un objeto de constructor con parámetros obligatorios y configure los parámetros opcionales con el método setter, luego

27 de abril de 2024

[Effective Java] Item 5. Utilice la inyección de dependencia en lugar de especificar recursos Si una clase depende de recursos externos, es mejor no usar singletons ni clases de utilidad estáticas. La inyección de dependencia puede mejorar la flexibilidad, la reutilización y la facilidad de prueba de la clase, y el uso del patrón de método de fábr

28 de abril de 2024

[Effective Java] Item 4. Use a private constructor to prevent instantiation Las clases de utilidad que contienen solo métodos y campos estáticos deben configurar el modificador de acceso de su constructor como privado para evitar la creación de instancias. Esto evita que los usuarios asuman que el constructor es generado automáti

28 de abril de 2024

[Javascript] Estructura de objetos (V8) El objeto JavaScript en el motor V8 se optimiza como una estructura, según el estado, en un modo rápido y se convierte en un modo de diccionario que funciona como un mapa hash. El modo rápido es rápido cuando la clave y el valor son casi fijos, pero cuand
곽경직
곽경직
곽경직
곽경직
곽경직

18 de marzo de 2024

[Concurrencia] Operación atómica: Memory Fence y Memory Ordering Esta publicación de blog explica cómo tener en cuenta el orden de la memoria en las operaciones atómicas y la importancia de las opciones de ordenación. Se explica en detalle las diversas opciones de ordenación, como Relaxed, Acquire, Release, AcqRel y Se
곽경직
곽경직
곽경직
곽경직
곽경직

12 de abril de 2024

Para mí, que quiero dar buenas críticas ¿Quieres aprender métodos de retroalimentación efectivos para el crecimiento de tus compañeros de equipo? Este artículo enfatiza la importancia del 'feedforward', que consiste en descubrir las fortalezas de tus compañeros de equipo y elogiarlos, y ofrece
울림
울림
울림
울림

18 de marzo de 2024

[Pruebas prácticas de maestro de materiales metálicos] Solución 36 Publicación de blog que trata sobre el concepto, los métodos y los casos de aplicación de los tratamientos térmicos y los ensayos no destructivos de los materiales metálicos, como el tratamiento térmico, el ensayo de partículas magnéticas y el ensayo por
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi
blog.naver.com/gksmftordldi

23 de abril de 2024

Modelado de datos físico El modelado de datos físico es el proceso de diseñar las tablas de una base de datos relacional para que sean realmente utilizables. Se busca optimizar el rendimiento mediante la eficiencia del espacio de almacenamiento, el particionamiento de datos, el d
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그
제이의 블로그

9 de abril de 2024

[Sin ser un experto, sobrevivir como desarrollador] 16. Consejos para crear una cartera para desarrolladores junior Un desarrollador junior (especialmente uno que no tiene formación en el campo) debe describir claramente no solo las tecnologías en su portafolio, sino también los servicios o funciones que ha desarrollado. Por ejemplo, en el caso de un proyecto de "Comun
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

3 de abril de 2024