tutorial reflexion reflect por metodo invocar introspección example ejemplos ejemplo java reflection terminology

reflect - reflexion java ejemplos



¿Qué es la reflexión y por qué es útil? (20)

Reflexión es la capacidad de un lenguaje para inspeccionar y llamar dinámicamente clases, métodos, atributos, etc. 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 sabe en tiempo de compilación (por ejemplo, si lo declaró como un Object ). Esto puede parecer trivial, pero tal La reflexión no es posible en lenguajes menos dinámicos como C++ . Usos más avanzados le permite listar 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 el momento de la compilación, lo que los hace más dinámicos, ya que se pueden vincular durante el tiempo de ejecución. El código puede escribirse contra interfaces conocidas, pero las clases reales que se usarán pueden crearse mediante la reflexión de los archivos de configuración.

Muchos de los marcos modernos utilizan la reflexión ampliamente por esta misma razón. La mayoría de los otros lenguajes modernos también utilizan la reflexión, y en los lenguajes de scripting (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.

¿Qué es la reflexión y por qué es útil?

Estoy particularmente interesado en Java, pero asumo que los principios son los mismos en cualquier idioma.


¡La reflexión es un mecanismo clave para permitir que una aplicación o marco funcione con código que aún no se ha escrito!

Tomemos por ejemplo su archivo web.xml típico. Esto contendrá una lista de elementos de servlet, que contienen elementos de clase de 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 el análisis de XML (JAXP) . Cuando un proveedor de analizador XML está "conectado" a través de propiedades del sistema 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 beans y su uso intensivo de proxies.


Como su propio nombre sugiere, refleja lo que tiene, por ejemplo, método de clase, etc., además de proporcionar una función para invocar el método creando una instancia dinámicamente en tiempo de ejecución.

Es utilizado por muchos marcos y aplicaciones bajo la madera para invocar servicios sin conocer realmente el código.


Desde la page documentación de java page

java.lang.reflect paquete java.lang.reflect proporciona clases e interfaces para obtener información reflexiva sobre clases y objetos. La reflexión permite el acceso programático a la información sobre los campos, métodos y constructores de las clases cargadas, y el uso de campos, métodos y constructores reflejados para operar en sus contrapartes subyacentes, dentro de las restricciones de seguridad.

AccessibleObject permite la supresión de las verificaciones de acceso si el ReflectPermission necesario está disponible.

Las clases en este paquete, junto con java.lang.Class acomodan aplicaciones como depuradores, intérpretes, inspectores de objetos, exploradores de clases y servicios como Object Serialization y JavaBeans que necesitan acceso a los miembros públicos de un objeto objetivo (basado en su clase runtime) o los miembros declarados por una clase dada

Incluye las siguientes funcionalidades.

  1. Obtención de objetos de clase,
  2. Examinar las propiedades de una clase (campos, métodos, constructores),
  3. Configuración y obtención de valores de campo,
  4. Invocando métodos,
  5. Creando nuevas instancias de objetos.

Eche un vistazo a este enlace de documentation para los métodos expuestos por Class clase.

De este article (por Dennis Sosnoski, presidente, Sosnoski Software Solutions, Inc) y este article (security-explorations pdf):

Puedo ver inconvenientes considerables que los usos de Reflexión.

Usuario de Reflexión:

  1. Proporciona una forma muy versátil de vincular dinámicamente los componentes del programa.
  2. Es útil para crear bibliotecas que trabajan con objetos de manera muy general.

Inconvenientes de la reflexión:

  1. La reflexión es mucho más lenta que el código directo cuando se usa para el acceso a campos y métodos.
  2. Puede ocultar lo que realmente está sucediendo dentro de su código
  3. Elude el código fuente puede crear problemas de mantenimiento.
  4. El código de reflexión también es más complejo que el código directo correspondiente
  5. Permite la violación de restricciones de seguridad clave de Java, como la protección de acceso a datos y la seguridad de tipos

Abusos generales:

  1. Carga de clases restringidas,
  2. Obtención de referencias a constructores, métodos o campos de una clase restringida,
  3. Creación de nuevas instancias de objetos, invocación de métodos, obtención o configuración de valores de campo de una clase restringida.

Eche un vistazo a esta pregunta de SE sobre el abuso de la reflexión:

¿Cómo leo un campo privado en Java?

Resumen:

El uso inseguro de sus funciones realizadas desde dentro de un código de sistema también puede llevar fácilmente al compromiso de un modo de seguridad Java l. Así que usa esta característica con moderación


Ejemplo simple para la reflexión. En un juego de ajedrez, no sabes qué moverá el usuario en el 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.

public class Test { public void firstMoveChoice(){ System.out.println("First Move"); } public void secondMOveChoice(){ System.out.println("Second Move"); } public void thirdMoveChoice(){ System.out.println("Third Move"); } public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Test test = new Test(); Method[] method = test.getClass().getMethods(); //firstMoveChoice method[0].invoke(test, null); //secondMoveChoice method[1].invoke(test, null); //thirdMoveChoice method[2].invoke(test, null); } }


Ejemplo:
Tomemos, por ejemplo, una aplicación remota que le da a su aplicación un objeto que obtiene usando sus métodos API. Ahora, en función del objeto que necesite para 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 con una lógica diferente. Obviamente, la información del objeto está disponible en tiempo de ejecución, por lo que no se puede codificar de forma estática para realizar el cálculo, por lo que se utiliza la reflexión para instanciar el objeto de la clase que necesita para realizar el cálculo en función Objeto recibido del proveedor.


El reflejo del nombre se utiliza 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 escritura estática de Java no está realmente diseñado para admitir esto a menos que el objeto se ajuste a una interfaz conocida, pero mediante la reflexión, su código puede mirar el objeto y descubrir si tiene un método llamado ''doSomething'' y luego llamarlo si querer.

Entonces, para darle un ejemplo de código de esto en Java (imagine que el objeto en cuestión es foo):

Method method = foo.getClass().getMethod("doSomething", null); method.invoke(foo, null);

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á al ejecutar la prueba de la unidad.

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 de tipos estáticos que admiten la reflexión (como C #). En los idiomas escritos dinámicamente, 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 el 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:

La capacidad de inspeccionar el código en el sistema y ver los tipos de objetos no es reflejo, sino más bien Tipo de introspección. La reflexión es, entonces, la capacidad de realizar modificaciones en el tiempo de ejecución haciendo uso de la introspección. La distinción es necesaria aquí ya que algunos idiomas admiten la introspección, pero no admiten la reflexión. Un ejemplo es C ++


Java Reflection es bastante potente y puede ser muy útil. Java Reflection permite inspeccionar clases, interfaces, campos y métodos en tiempo de ejecución, sin saber los nombres de las clases, métodos, etc. en tiempo de compilación. También es posible crear una instancia 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 usar la reflexión:

Method[] methods = MyObject.class.getMethods(); for(Method method : methods){ System.out.println("method = " + method.getName()); }

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.

Exactamente cómo todo esto funciona se explica aquí.

Edición : Después de casi 1 año, estoy editando esta respuesta mientras leía sobre la reflexión, tengo algunos usos más de la Reflexión.

  • Spring usa una configuración de bean como:


<bean id="someID" class="com.example.Foo"> <property name="someField" value="someValue" /> </bean>

Cuando el contexto Spring procesa este elemento <bean>, utilizará Class.forName (String) con el argumento "com.example.Foo" para crear una instancia de esa Clase.

A continuación, volverá a utilizar la reflexión para obtener el setter apropiado para el elemento <property> y establecer su valor en el valor especificado.

  • Junit utiliza Reflection especialmente para probar métodos privados / protegidos.

Para los métodos privados,

Method method = targetClass.getDeclaredMethod(methodName, argClasses); method.setAccessible(true); return method.invoke(targetObject, argObjects);

Para campos privados,

Field field = targetClass.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value);


Java Reflection permite inspeccionar clases, interfaces, campos y métodos en tiempo de ejecución, sin saber los nombres de las clases, métodos, etc. Sobre todo a nivel marco, se pueden lograr los máximos beneficios de la reflexión. El código de bytes que se compila si necesita una modificación adicional en el tiempo de ejecución para su examen, modificación, adición de más código de bytes dentro de sí mismo u otro programa u otro marco a nivel de método, nivel de instancia de instancia, nivel de constructor, reflexión de nivel de anotación puede ser útil.

Supongamos que tiene un método add(Int a,int b) . El código byte equivalente es B1 . Si supones que tienes 1000 métodos nombrados add en tu sistema. Ahora desea verificar el valor de los parámetros a y b antes de llamar al método add . Por lo tanto, puede pegar su código a otro programa o marco que use la reflexión para examinar dinámicamente el valor del código de byte utilizando Object.getClass.getMethod() . Hay varias clases para examinar. Puede agregar más operaciones antes de que se llame al método add . Pero, el programa en sí u otro programa o marco no conoce el objeto que tiene un método llamado add . Sobre todo en la inyección de dependencias, se utiliza principalmente el uso de la reflexión orientada a aspectos.


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 capacidad de "autoidentificación".

La reflexión en sí misma es una palabra para lenguajes de este tipo 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 otros individuos. 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 es que necesitamos reflexión en Java.


La reflexión le da la posibilidad de escribir código más 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 la introspección del objeto y la clase para detectar sus variables y métodos expuestos al mundo exterior.


La reflexión permite la creación de instancias de nuevos objetos, invocación de métodos y operaciones de obtención / establecimiento de variables de clase de forma dinámica en tiempo de ejecución sin tener conocimiento previo de su implementación.

Class myObjectClass = MyObject.class; Method[] method = myObjectClass.getMethods(); //Here the method takes a string parameter if there is no param, put null. Method method = aClass.getMethod("method_name", String.class); Object returnValue = method.invoke(null, "parameter-value1");

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, el suministro es nulo. Si el método no es estático, al invocar debe proporcionar una instancia de MyObject válida en lugar de nula.

Reflexión también le permite acceder a miembros / métodos privados de una clase:

public class A{ private String str= null; public A(String str) { this.str= str; } }

.

A obj= new A("Some value"); Field privateStringField = A.class.getDeclaredField("privateString"); //Turn off access check for this field privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(obj); System.out.println("fieldValue = " + fieldValue);

  • Para la inspección de clases (también conocida como introspección) no es necesario importar el paquete de reflexión ( java.lang.reflect ). Se puede acceder a los metadatos de clase a través de java.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.


No todos los idiomas admiten la reflexión, pero los principios suelen ser los mismos en los idiomas que la admiten.

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 de manera programada informació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 donde desee poder conectar dinámicamente clases en su código. Muchos de los mapeadores relacionales de objetos utilizan la reflexión para poder instanciar objetos desde bases de datos sin saber de antemano qué objetos van a usar. Las arquitecturas enchufables son otro lugar donde la reflexión es útil. Ser capaz de cargar dinámicamente el código y determinar si hay tipos allí que implementan la interfaz correcta para usar como un complemento es importante en esas situaciones.


Reflexión 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 motor de ejecución en función 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 conjunto (un .dll) en tiempo de ejecución y examinarlo, navegar por las clases y tomar acciones de acuerdo con lo que haya encontrado. 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 en todo momento 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 y así sucesivamente ...


Según mi entendimiento:

La reflexión permite al programador acceder a las entidades en el programa de forma dinámica. es decir, al codificar una aplicación si el programador desconoce una clase o sus métodos, puede utilizar dicha clase dinámicamente (en tiempo de ejecución) utilizando la reflexión.

Se usa frecuentemente en escenarios donde un nombre de clase cambia frecuentemente. Si surge tal situación, entonces es complicado para el programador volver a escribir la aplicación y cambiar el nombre de la clase una y otra vez.

En su lugar, al utilizar la reflexión, es necesario preocuparse por un nombre de clase posiblemente cambiante.


Solo quiero añadir algún punto a todo lo que se enumera.

Con la API de Reflection puede escribir el método universal toString() para cualquier objeto.

Es útil en la depuración.

Aquí hay un ejemplo:

class ObjectAnalyzer { private ArrayList<Object> visited = new ArrayList<Object>(); /** * Converts an object to a string representation that lists all fields. * @param obj an object * @return a string with the object''s class name and all field names and * values */ public String toString(Object obj) { if (obj == null) return "null"; if (visited.contains(obj)) return "..."; visited.add(obj); Class cl = obj.getClass(); if (cl == String.class) return (String) obj; if (cl.isArray()) { String r = cl.getComponentType() + "[]{"; for (int i = 0; i < Array.getLength(obj); i++) { if (i > 0) r += ","; Object val = Array.get(obj, i); if (cl.getComponentType().isPrimitive()) r += val; else r += toString(val); } return r + "}"; } String r = cl.getName(); // inspect the fields of this class and all superclasses do { r += "["; Field[] fields = cl.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); // get the names and values of all fields for (Field f : fields) { if (!Modifier.isStatic(f.getModifiers())) { if (!r.endsWith("[")) r += ","; r += f.getName() + "="; try { Class t = f.getType(); Object val = f.get(obj); if (t.isPrimitive()) r += val; else r += toString(val); } catch (Exception e) { e.printStackTrace(); } } } r += "]"; cl = cl.getSuperclass(); } while (cl != null); return r; } }


Uno 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.

import java.lang.reflect.Array; import java.lang.reflect.Field; public static String dump(Object o, int callCount) { callCount++; StringBuffer tabs = new StringBuffer(); for (int k = 0; k < callCount; k++) { tabs.append("/t"); } StringBuffer buffer = new StringBuffer(); Class oClass = o.getClass(); if (oClass.isArray()) { buffer.append("/n"); buffer.append(tabs.toString()); buffer.append("["); for (int i = 0; i < Array.getLength(o); i++) { if (i < 0) buffer.append(","); Object value = Array.get(o, i); if (value.getClass().isPrimitive() || value.getClass() == java.lang.Long.class || value.getClass() == java.lang.String.class || value.getClass() == java.lang.Integer.class || value.getClass() == java.lang.Boolean.class ) { buffer.append(value); } else { buffer.append(dump(value, callCount)); } } buffer.append(tabs.toString()); buffer.append("]/n"); } else { buffer.append("/n"); buffer.append(tabs.toString()); buffer.append("{/n"); while (oClass != null) { Field[] fields = oClass.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { buffer.append(tabs.toString()); fields[i].setAccessible(true); buffer.append(fields[i].getName()); buffer.append("="); try { Object value = fields[i].get(o); if (value != null) { if (value.getClass().isPrimitive() || value.getClass() == java.lang.Long.class || value.getClass() == java.lang.String.class || value.getClass() == java.lang.Integer.class || value.getClass() == java.lang.Boolean.class ) { buffer.append(value); } else { buffer.append(dump(value, callCount)); } } } catch (IllegalAccessException e) { buffer.append(e.getMessage()); } buffer.append("/n"); } oClass = oClass.getSuperclass(); } buffer.append(tabs.toString()); buffer.append("}/n"); } return buffer.toString(); }


Reflection tiene muchos usos . Con el que estoy más familiarizado, es poder crear código sobre la marcha.

IE: clases dinámicas, funciones, constructores - basados ​​en cualquier dato (xml / array / sql results / hardcoded / etc ..)


Reflexión es una API que se utiliza para examinar o modificar el comportamiento de los métodos, las clases y las interfaces en tiempo de ejecución.

  1. Las clases requeridas para la reflexión se proporcionan bajo el java.lang.reflect package .
  2. La reflexión nos da información sobre la clase a la que pertenece un objeto y también los métodos de esa clase que se pueden ejecutar utilizando el objeto.
  3. A través de la reflexión, podemos invocar métodos en tiempo de ejecución independientemente del especificador de acceso utilizado con ellos.

Los paquetes java.lang y java.lang.reflect proporcionan clases para la reflexión de java.

La reflexión se puede utilizar para obtener información sobre:

  1. Clase El método getClass() se usa para obtener el nombre de la clase a la que pertenece un objeto.

  2. Constructores El método getConstructors() se utiliza para obtener los constructores públicos de la clase a la que pertenece un objeto.

  3. Métodos El método getMethods() se usa para obtener los métodos públicos de la clase a la que pertenece un objeto.

La API de reflexión se utiliza principalmente en:

IDE (entorno de desarrollo integrado), por ejemplo, Eclipse, MyEclipse, NetBeans, etc.
Herramientas de depuración y prueba, etc.

Ventajas de usar la reflexión:

Funciones 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 con sus nombres completos.

Herramientas de depuración y prueba: los depuradores utilizan la propiedad de la reflexión para examinar a los miembros privados en las clases.

Inconvenientes:

Overhead de rendimiento: las operaciones reflectivas tienen un rendimiento más lento que sus contrapartes no reflectivas, y deben evitarse en las 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


Usos de la reflexión

Reflection es comúnmente utilizado por los 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 de Java. Esta es una característica relativamente avanzada y solo debe ser utilizada por desarrolladores que tengan un conocimiento sólido 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 otra manera serían imposibles.

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 completos. 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 miembros privados en las clases. Los arneses de prueba pueden hacer uso de la reflexión para llamar sistemáticamente a un conjunto de API detectables definidas en una clase, para garantizar un alto nivel de cobertura de código en una serie de pruebas.

Inconvenientes de la reflexión

La reflexión es poderosa, pero no debe utilizarse indiscriminadamente. Si es posible realizar una operación sin usar la reflexión, entonces es preferible evitar usarla. Las siguientes preocupaciones deben tenerse en cuenta al acceder al código a través de la reflexión.

  • Overhead de rendimiento

Debido a que la reflexión implica tipos que se resuelven dinámicamente, no se pueden realizar ciertas optimizaciones de máquinas virtuales Java. En consecuencia, las operaciones de reflexión tienen un rendimiento más lento que sus contrapartes no reflexivas y deben evitarse en las secciones de código que se llaman con frecuencia en aplicaciones sensibles al rendimiento.

  • Restricciones de seguridad

La reflexión 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.

  • Exposición de los internos

Dado que la reflexión permite que el código realice operaciones que serían ilegales en el código no reflexivo, como el acceso a campos y métodos privados, el uso de la reflexión puede producir efectos secundarios inesperados, que pueden hacer que el código sea disfuncional y puede 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 reflexión