제이온

[Java] Concepto y uso de la Reflexión

Creado: 2024-04-25

Creado: 2024-04-25 22:27

¿Qué es la Reflexión?

La reflexión es una API que permite, a través de un objeto de tipo Class cargado en el área de memoria Heap, crear instancias de la clase deseada y acceder a los campos y métodos de la instancia sin importar los modificadores de acceso.



Aquí, la clase cargada se refiere a que el cargador de clases de la JVM ha completado la carga del archivo de clase y ha creado un objeto de tipo Classque contiene la información de dicha clase y la ha almacenado en el área de memoria Heap. Es importante tener en cuenta que esto es diferente a los objetos creados con la palabra clave new. Si no entiendes bien el objeto de tipo Class, te recomiendo que consultes la documentación JDK de java.lang.class.


Cómo usarla

Antes de usar la reflexión, necesitamos obtener el objeto de tipo Class cargado en el área de memoria Heap. Hay tres maneras de hacerlo.


  • Obtenerla con Clase.class
  • Obtenerla con Instancia.getClass()
  • Obtenerla con Class.forName("NombreDeLaClase")


Podemos ver que las tres formas de obtener la instancia de tipo Class son iguales. El valor hash es el mismo en todos los casos, por lo que se puede usar cualquiera según la situación.


Ahora, usando el objeto de tipo Class, podemos crear instancias de la clase y acceder a sus campos y métodos sin importar los modificadores de acceso. Primero, vamos a crear una instancia de la clase.


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

Finalmente, vamos a acceder a los campos y métodos de la instancia sin importar los modificadores de acceso.

Podemos obtener todas las variables de instancia de la clase usando getDeclaredFileds(), obtener el valor del campo usando get() y modificar el valor del campo usando set(). Es importante tener en cuenta que cuando se accede a un campo con el modificador de acceso private, se debe establecer el parámetro de setAccessible() en true.


Los métodos también se pueden obtener usando getDeclaredMethod(). En este caso, se debe pasar el nombre del método y el tipo de parámetro como argumentos. De manera similar, cuando se accede a un método con el modificador de acceso private, se debe establecer el parámetro de setAccessible() en true. Finalmente, se puede llamar al método obtenido a través de la API de reflexión usando invoke().


Ventajas y desventajas

  • Ventajas
    • Tiene la flexibilidad de crear instancias de clases y acceder a campos y métodos sin importar los modificadores de acceso en tiempo de ejecución, lo que permite realizar las tareas necesarias.
  • Desventajas
    • Socava la encapsulación.
    • Dado que crea instancias en tiempo de ejecución, no se puede comprobar el tipo en tiempo de compilación.
    • Dado que crea instancias en tiempo de ejecución, es difícil comprender el flujo de trabajo concreto.
    • El rendimiento es más lento que acceder a campos y métodos directamente, ya que usa reflexión. (No siempre es más lento).


Razones para usarla

La API de reflexión permite acceder a la información de la clase en tiempo de ejecución y manipularla a voluntad. Incluso se pueden manipular campos y métodos declarados con el modificador de acceso private. Esto parece una técnica que no debería usarse porque rompe la encapsulación, que es un concepto importante en el diseño orientado a objetos.


En proyectos pequeños a nivel de consola, el desarrollador puede comprender fácilmente todos los objetos y relaciones de dependencia que se usarán en el programa en tiempo de compilación. Sin embargo, en proyectos a gran escala como los frameworks, es difícil comprender la gran cantidad de objetos y relaciones de dependencia. En tales casos, la reflexión permite crear dinámicamente clases y establecer relaciones de dependencia.


Por ejemplo, en Spring Bean Factory, si simplemente agregamos las anotaciones @Controller, @Service, @Repository, etc., Bean Factory crea y gestiona automáticamente las clases a las que se adjuntan estas anotaciones. El desarrollador no ha especificado explícitamente estas clases en Bean Factory, pero esto es posible gracias a la reflexión. Busca en tiempo de ejecución las clases con estas anotaciones y, si las encuentra, usa la reflexión para crear una instancia de la clase, inyectar los campos necesarios y almacenarlos en Bean Factory.


Por supuesto, como mencionamos anteriormente, socava la encapsulación, por lo que es mejor usarla solo cuando sea necesario.


Fuentes

Comentarios0