¿Qué es la reflexión y por qué es útil?
Estoy particularmente interesado en Java, pero supongo que los principios son los mismos en cualquier lenguaje.
java
reflection
terminology
Lehane
fuente
fuente
@Jailbreak
. Proporciona acceso directo y de tipo seguro a campos privados, métodos, etc. Deje que el compilador de Java verifique de manera segura su código y permita que Manifold genere el acceso de reflexión subyacente para usted. Más información: manifold.systems/docs.html#type-safe-reflectionRespuestas:
El reflejo del nombre se usa para describir el código que puede inspeccionar otro código en el mismo sistema (o en sí mismo).
Por ejemplo, supongamos que tiene un objeto de un tipo desconocido en Java, y le gustaría llamar a un método 'doSomething' si existe. El sistema de tipeo estático de Java no está realmente diseñado para soportar esto a menos que el objeto se ajuste a una interfaz conocida, pero usando la reflexión, su código puede mirar el objeto y descubrir si tiene un método llamado 'doSomething' y luego llamarlo si usted querer.
Entonces, para darle un ejemplo de código de esto en Java (imagine que el objeto en cuestión es foo):
Un caso de uso muy común en Java es el uso con anotaciones. JUnit 4, por ejemplo, utilizará la reflexión para buscar en sus clases los métodos etiquetados con la anotación @Test, y luego los llamará cuando ejecute la prueba unitaria.
Hay algunos buenos ejemplos de reflexión para comenzar en http://docs.oracle.com/javase/tutorial/reflect/index.html
Y finalmente, sí, los conceptos son bastante similares en otros lenguajes estáticamente tipados que admiten la reflexión (como C #). En lenguajes de tipo dinámico, el caso de uso descrito anteriormente es menos necesario (ya que el compilador permitirá que se llame a cualquier método en cualquier objeto, fallando en tiempo de ejecución si no existe), pero el segundo caso es buscar métodos que están marcados o el trabajo de cierta manera sigue siendo común.
Actualización de un comentario:
fuente
Method
,Constructor
,Modifier
,Field
,Member
,, básicamente, al parecer, todos exceptoClass
) están dentro deljava.lang.*reflect*
paquete. ¿Quizás el concepto "reflexión" incluye tanto la "introspección de tipo" como la modificación en tiempo de ejecución?Por ejemplo, todos los objetos en Java tienen el método
getClass()
, que le permite determinar la clase del objeto incluso si no lo conoce en tiempo de compilación (por ejemplo, si lo declaró como unObject
), esto puede parecer trivial, pero tal reflexión no es posible en lenguajes menos dinámicos comoC++
. Los usos más avanzados le permiten enumerar y llamar a métodos, constructores, etc.La reflexión es importante, ya que le permite escribir programas que no tienen que "saber" todo en tiempo de compilación, lo que los hace más dinámicos, ya que pueden vincularse en tiempo de ejecución. El código se puede escribir en interfaces conocidas, pero las clases reales que se utilizarán se pueden instanciar utilizando la reflexión de los archivos de configuración.
Muchos marcos modernos usan la reflexión ampliamente por esta misma razón. La mayoría de los otros lenguajes modernos también usan la reflexión, y en los lenguajes de script (como Python) están aún más integrados, ya que se siente más natural dentro del modelo de programación general de esos lenguajes.
fuente
C++
tiene información de tipo de tiempo de ejecución. RTTIUno de mis usos favoritos de la reflexión es el siguiente método de volcado de Java. Toma cualquier objeto como parámetro y utiliza la API de reflexión de Java para imprimir cada nombre y valor de campo.
fuente
callCount
debe establecerse en cero. Su valor se utiliza para determinar cuántas pestañas deben preceder a cada línea de salida: cada vez que dump necesita volcar un "subobject", la salida se imprimirá como anidada en el padre. Ese método resulta útil cuando se envuelve en otro. ConsidereprintDump(Object obj){ System.out.println(dump(obj, 0)); }
.Usos de la reflexión
La reflexión es utilizada comúnmente por programas que requieren la capacidad de examinar o modificar el comportamiento en tiempo de ejecución de las aplicaciones que se ejecutan en la máquina virtual Java. Esta es una característica relativamente avanzada y debe ser utilizada solo por desarrolladores que tengan una buena comprensión de los fundamentos del lenguaje. Con esa advertencia en mente, la reflexión es una técnica poderosa y puede permitir que las aplicaciones realicen operaciones que de otro modo serían imposibles.
Características de extensibilidad
Una aplicación puede hacer uso de clases externas definidas por el usuario creando instancias de objetos de extensibilidad utilizando sus nombres totalmente calificados. Navegadores de clases y entornos de desarrollo visual Un navegador de clases debe poder enumerar los miembros de las clases. Los entornos de desarrollo visual pueden beneficiarse al hacer uso de la información de tipo disponible en la reflexión para ayudar al desarrollador a escribir el código correcto. Depuradores y herramientas de prueba Los depuradores deben poder examinar a los miembros privados en las clases. Los arneses de prueba pueden hacer uso de la reflexión para llamar sistemáticamente a un conjunto de APIs descubribles definidos en una clase, para garantizar un alto nivel de cobertura de código en un conjunto de pruebas.
Inconvenientes de la reflexión
La reflexión es poderosa, pero no debe usarse indiscriminadamente. Si es posible realizar una operación sin usar la reflexión, entonces es preferible evitar usarla. Deben tenerse en cuenta las siguientes inquietudes al acceder al código a través de la reflexión.
Debido a que la reflexión involucra tipos que se resuelven dinámicamente, ciertas optimizaciones de máquinas virtuales Java no se pueden realizar. En consecuencia, las operaciones reflectantes tienen un rendimiento más lento que sus contrapartes no reflectantes y deben evitarse en secciones de código que se llaman con frecuencia en aplicaciones sensibles al rendimiento.
Reflection requiere un permiso de tiempo de ejecución que puede no estar presente cuando se ejecuta bajo un administrador de seguridad. Esto es una consideración importante para el código que debe ejecutarse en un contexto de seguridad restringido, como en un Applet.
Dado que la reflexión permite que el código realice operaciones que serían ilegales en el código no reflectante, como acceder a campos y métodos privados, el uso de la reflexión puede provocar efectos secundarios inesperados, que pueden hacer que el código sea disfuncional y destruir la portabilidad. El código reflexivo rompe las abstracciones y, por lo tanto, puede cambiar el comportamiento con las actualizaciones de la plataforma.
fuente: La API de Reflection
fuente
¡Reflection es un mecanismo clave para permitir que una aplicación o marco funcione con código que aún no se ha escrito!
Tome por ejemplo su típico archivo web.xml. Esto contendrá una lista de elementos de servlet, que contienen elementos de clase servlet anidados. El contenedor de servlets procesará el archivo web.xml y creará una nueva instancia de cada clase de servlet a través de la reflexión.
Otro ejemplo sería la API de Java para análisis XML (JAXP) . Cuando un proveedor de analizador XML se 'conecta' a través de propiedades de sistema bien conocidas, que se utilizan para construir nuevas instancias a través de la reflexión.
Y, por último, el ejemplo más completo es Spring, que utiliza la reflexión para crear sus granos, y por su uso intensivo de proxies.
fuente
No todos los idiomas admiten la reflexión, pero los principios suelen ser los mismos en los idiomas que lo admiten.
La reflexión es la capacidad de "reflexionar" sobre la estructura de su programa. O más concreto. Para ver los objetos y las clases que tiene y obtener información mediante programación sobre los métodos, campos e interfaces que implementan. También puedes mirar cosas como anotaciones.
Es útil en muchas situaciones. En cualquier lugar que desee poder conectar dinámicamente clases en su código. Muchos de los mapeadores relacionales de objetos usan la reflexión para poder instanciar objetos de bases de datos sin saber de antemano qué objetos van a usar. Las arquitecturas enchufables son otro lugar donde la reflexión es útil. Poder cargar código dinámicamente y determinar si hay tipos allí que implementen la interfaz correcta para usar como complemento es importante en esas situaciones.
fuente
La reflexión permite la creación de instancias de nuevos objetos, la invocación de métodos y las operaciones get / set en variables de clase dinámicamente en tiempo de ejecución sin tener conocimiento previo de su implementación.
En el ejemplo anterior, el parámetro nulo es el objeto sobre el que desea invocar el método. Si el método es estático, debe proporcionar nulo. Si el método no es estático, al invocarlo debe proporcionar una instancia válida de MyObject en lugar de nula.
Reflection también le permite acceder a miembros / métodos privados de una clase:
.
java.lang.reflect
). Se puede acceder a los metadatos de la clase a través dejava.lang.Class
.Reflection es una API muy poderosa, pero puede ralentizar la aplicación si se usa en exceso, ya que resuelve todos los tipos en tiempo de ejecución.
fuente
Java Reflection es bastante potente y puede ser muy útil. Java Reflection hace posible inspeccionar clases, interfaces, campos y métodos en tiempo de ejecución, sin conocer los nombres de las clases, métodos, etc. en tiempo de compilación. También es posible crear instancias de nuevos objetos, invocar métodos y obtener / establecer valores de campo utilizando la reflexión.
Un ejemplo rápido de Java Reflection para mostrarle cómo se ve el uso de la reflexión:
Este ejemplo obtiene el objeto Class de la clase llamada MyObject. Usando el objeto de clase, el ejemplo obtiene una lista de los métodos en esa clase, itera los métodos e imprime sus nombres.
Aquí se explica exactamente cómo funciona todo esto
Editar : Después de casi 1 año, estoy editando esta respuesta, ya que mientras leía sobre la reflexión, obtuve algunos usos más de Reflection.
Cuando el contexto Spring procesa este elemento <bean>, usará Class.forName (String) con el argumento "com.example.Foo" para crear una instancia de esa clase.
Luego volverá a usar la reflexión para obtener el setter apropiado para el elemento <property> y establecer su valor en el valor especificado.
Para métodos privados,
Para campos privados,
fuente
Ejemplo:
Tomemos, por ejemplo, una aplicación remota que le da a su aplicación un objeto que obtiene utilizando sus métodos API. Ahora, según el objeto, es posible que deba realizar algún tipo de cálculo.
El proveedor garantiza que el objeto puede ser de 3 tipos y necesitamos realizar cálculos basados en qué tipo de objeto.
Por lo tanto, podríamos implementar en 3 clases, cada una de las cuales contiene una lógica diferente. Obviamente, la información del objeto está disponible en tiempo de ejecución, por lo que no puede codificar estáticamente para realizar el cálculo, por lo tanto, la reflexión se utiliza para instanciar el objeto de la clase que necesita para realizar el cálculo en función del objeto recibido del proveedor.
fuente
instanceof
para determinar el tipo de objeto en tiempo de ejecución?Ejemplo simple para la reflexión. En un juego de ajedrez, no sabes qué moverá el usuario en tiempo de ejecución. La reflexión se puede utilizar para llamar a métodos que ya están implementados en tiempo de ejecución:
fuente
Reflection es una API que se utiliza para examinar o modificar el comportamiento de métodos, clases e interfaces en tiempo de ejecución.
java.lang.reflect package
.Los paquetes
java.lang
yjava.lang.reflect
proporcionan clases para la reflexión de Java.La reflexión se puede utilizar para obtener información sobre:
Clase El
getClass()
método se utiliza para obtener el nombre de la clase a la que pertenece un objeto.Constructores El
getConstructors()
método se utiliza para obtener los constructores públicos de la clase a la que pertenece un objeto.Métodos El
getMethods()
método se utiliza para obtener los métodos públicos de la clase a la que pertenece un objeto.La API de Reflection se usa principalmente en:
IDE (entorno de desarrollo integrado), por ejemplo, Eclipse, MyEclipse, NetBeans, etc.
Depurador y herramientas de prueba, etc.
Ventajas de usar la reflexión:
Características de extensibilidad: una aplicación puede hacer uso de clases externas definidas por el usuario mediante la creación de instancias de objetos de extensibilidad utilizando sus nombres totalmente calificados.
Herramientas de depuración y prueba: los depuradores usan la propiedad de reflexión para examinar a los miembros privados en las clases.
Inconvenientes:
Sobrecarga de rendimiento: las operaciones reflectantes tienen un rendimiento más lento que sus contrapartes no reflectantes, y deben evitarse en secciones de código que se llaman con frecuencia en aplicaciones sensibles al rendimiento.
Exposición de elementos internos: el código reflexivo rompe las abstracciones y, por lo tanto, puede cambiar el comportamiento con las actualizaciones de la plataforma.
Ref: Java Reflection javarevisited.blogspot.in
fuente
Según mi entendimiento:
La reflexión permite al programador acceder a las entidades en el programa de forma dinámica. es decir, mientras codifica una aplicación si el programador desconoce una clase o sus métodos, puede utilizar dicha clase dinámicamente (en tiempo de ejecución) mediante el uso de la reflexión.
Se usa con frecuencia en escenarios donde el nombre de una clase cambia con frecuencia. Si surge tal situación, es complicado para el programador reescribir la aplicación y cambiar el nombre de la clase una y otra vez.
En cambio, al usar la reflexión, es necesario preocuparse por un posible nombre de clase cambiante.
fuente
Reflection es un conjunto de funciones que le permite acceder a la información de tiempo de ejecución de su programa y modificar su comportamiento (con algunas limitaciones).
Es útil porque le permite cambiar el comportamiento del tiempo de ejecución dependiendo de la metainformación de su programa, es decir, puede verificar el tipo de retorno de una función y cambiar la forma en que maneja la situación.
En C #, por ejemplo, puede cargar un ensamblado (un .dll) en tiempo de ejecución y examinarlo, navegar a través de las clases y realizar acciones de acuerdo con lo que encontró. También le permite crear una instancia de una clase en tiempo de ejecución, invocar su método, etc.
¿Dónde puede ser útil? No es útil siempre sino para situaciones concretas. Por ejemplo, puede usarlo para obtener el nombre de la clase para fines de registro, para crear dinámicamente controladores para eventos de acuerdo con lo que se especifica en un archivo de configuración, etc.
fuente
Solo quiero agregar algún punto a todo lo que estaba en la lista.
Con Reflection API puedes escribir un
toString()
método universal para cualquier objeto.Es útil en la depuración.
Aquí hay un ejemplo:
fuente
La reflexión es dejar que el objeto vea su apariencia. Este argumento no parece tener nada que ver con la reflexión. De hecho, esta es la habilidad de "autoidentificación".
Reflexión en sí es una palabra para tales lenguajes que carecen de la capacidad de autoconocimiento y autodetección como Java y C #. Debido a que no tienen la capacidad de autoconocimiento, cuando queremos observar cómo se ve, debemos tener otra cosa para reflexionar sobre cómo se ve. Excelentes lenguajes dinámicos como Ruby y Python pueden percibir su propio reflejo sin la ayuda de otras personas. Podemos decir que el objeto de Java no puede percibir cómo se ve sin un espejo, que es un objeto de la clase de reflexión, pero un objeto en Python puede percibirlo sin un espejo. Por eso necesitamos reflexión en Java.
fuente
Desde la página de documentación de Java
AccessibleObject
permite la supresión de las comprobaciones de acceso siReflectPermission
es necesario .Las clases en este paquete, junto con
java.lang.Class
aplicaciones de acomodo como depuradores, intérpretes, inspectores de objetos, buscadores de clases y servicios comoObject Serialization
yJavaBeans
que necesitan acceso a los miembros públicos de un objeto de destino (en función de su clase de tiempo de ejecución) o los miembros declarados por una clase dadaIncluye la siguiente funcionalidad.
Eche un vistazo a este enlace de documentación para conocer los métodos expuestos por
Class
clase.De este artículo (por Dennis Sosnoski, Presidente, Sosnoski Software Solutions, Inc) y este artículo (security-explorations pdf):
Puedo ver inconvenientes considerables que los usos de usar Reflection
Usuario de Reflexión:
Inconvenientes de la reflexión:
Abusos generales:
Eche un vistazo a esta pregunta SE con respecto a la función de abuso de reflexión:
¿Cómo leo un campo privado en Java?
Resumen:
El uso inseguro de sus funciones realizadas desde un código del sistema también puede llevar fácilmente al compromiso de un modo de seguridad Java l. Así que usa esta función con moderación
fuente
Woozle
examine otras clases en el inicio para ver cuáles tienen unRegisterAsWoozleHelper()
método estático e invoque todos los métodos que encuentre con una devolución de llamada que puedan usar para hablarWoozle
sobre ellos mismos, evitando necesita usar Reflection mientras, por ejemplo, deserializa datos.Como su propio nombre sugiere, refleja lo que contiene, por ejemplo, el método de clase, etc., además de proporcionar características para invocar el método creando instancia dinámicamente en tiempo de ejecución.
Es utilizado por muchos frameworks y aplicaciones bajo el bosque para invocar servicios sin conocer realmente el código.
fuente
Reflection te da la capacidad de escribir más código genérico. Le permite crear un objeto en tiempo de ejecución y llamar a su método en tiempo de ejecución. Por lo tanto, el programa puede ser altamente parametrizado. También permite introspectar el objeto y la clase para detectar sus variables y métodos expuestos al mundo exterior.
fuente
Reflection
Tiene muchos usos . El que estoy más familiarizado es poder crear código sobre la marcha.fuente
Quiero responder a esta pregunta con un ejemplo. En primer lugar, el
Hibernate
proyecto se utilizaReflection API
para generarCRUD
declaraciones para cerrar el abismo entre la aplicación en ejecución y el almacén de persistencia. Cuando las cosas cambian en el dominio,Hibernate
deben saber sobre ellas para persistirlas en el almacén de datos y viceversa.Alternativamente funciona
Lombok Project
. Simplemente inyecta código en tiempo de compilación, lo que hace que el código se inserte en sus clases de dominio. (Creo que está bien para getters y setters)Hibernate
elegidoreflection
porque tiene un impacto mínimo en el proceso de compilación de una aplicación.Y de Java 7 tenemos
MethodHandles
, que funciona comoReflection API
. En proyectos, para trabajar con registradores, simplemente copiamos y pegamos el siguiente código:Porque es difícil cometer un error tipográfico en este caso.
fuente
Como creo que es mejor explicar con el ejemplo y ninguna de las respuestas parece hacer eso ...
Un ejemplo práctico de uso de reflexiones sería un servidor de lenguaje Java escrito en Java o un servidor de lenguaje PHP escrito en PHP, etc. El servidor de lenguaje brinda sus capacidades IDE como autocompletar, saltar a definición, ayuda contextual, tipos de sugerencias y más. Para que todos los nombres de etiquetas (palabras que se pueden completar automáticamente) muestren todas las coincidencias posibles a medida que escribe, el servidor de idiomas debe inspeccionar todo lo relacionado con la clase, incluidos los bloques de documentos y los miembros privados. Para eso necesita un reflejo de dicha clase.
Un ejemplo diferente sería una prueba unitaria de un método privado. Una forma de hacerlo es crear una reflexión y cambiar el alcance del método a público en la fase de configuración de la prueba. Por supuesto, uno puede argumentar que los métodos privados no deberían probarse directamente, pero ese no es el punto.
fuente