¿Qué es la reflexión?
«Reflection es comúnmente utilizado 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». Este concepto a menudo se mezcla con la introspección. Las siguientes son sus definiciones de Wiki:
- La introspección es la capacidad de un programa para examinar el tipo o las propiedades de un objeto en tiempo de ejecución.
- La reflexión es la capacidad de un programa para examinar y modificar la estructura y el comportamiento de un objeto en tiempo de ejecución.
Según sus definiciones, la introspección es un subconjunto de la reflexión. Algunos lenguajes admiten la introspección, pero no la reflexión, por ejemplo, C ++.
Ejemplo de introspección: el operador instanceof determina si un objeto pertenece a una clase en particular.
if(obj instanceof Dog){
Dog d = (Dog)obj;
d.bark();
}
|
if (obj instancia de Perro) {Perro d = (Perro) obj; d. corteza (); }
Ejemplo de reflexión: el método Class.forName () devuelve el objeto Class asociado con la clase / interfaz con el nombre dado (una cadena y un nombre calificado completo). El método forName hace que se inicialice la clase con el nombre.
// with reflection
Class<?> c = Class.forName("classpath.and.classname");
Object dog = c.newInstance();
Method m = c.getDeclaredMethod("bark", new Class<?>[0]);
m.invoke(dog);
|
// con reflexión Class > c = Class.forName («classpath.and.classname»); Objeto perro = c.newInstance (); Método m = c.getDeclaredMethod («ladrar», nueva clase >[0]); m.invoke (perro);
En Java, la reflexión se trata más de introspección, porque no se puede cambiar la estructura de un objeto. Hay algunas API para cambiar la accesibilidad de métodos y campos, pero no estructuras.
¿Por qué necesitamos la reflexión?
La reflexión nos permite:
- Examinar la clase de un objeto en tiempo de ejecución
- Construye un objeto para una clase en tiempo de ejecución
- Examinar el campo y el método de una clase en tiempo de ejecución
- Invocar cualquier método de un objeto en tiempo de ejecución
- Cambiar el indicador de accesibilidad de Constructor, Método y Campo
- etc.
La reflexión es la técnica común utilizada en los marcos.
Por ejemplo, JUnit usa la reflexión para mirar a través de métodos etiquetados con el @Prueba anotación, y luego llame a esos métodos cuando ejecute la prueba unitaria. (Aquí hay un conjunto de ejemplos de cómo usar JUnit).
Para los marcos web, los desarrolladores definen su propia implementación de interfaces y clases en los archivos de configuración. Mediante la reflexión, el marco inicializa dinámicamente las clases necesarias. Por ejemplo, Spring usa una configuración de frijoles como:
<bean id="someID" class="com.programcreek.Foo">
<property name="someField" value="someValue" />
</bean>
|
Cuando el contexto de Spring procesa este elemento , usará Class.forName (String) con el argumento «com.programcreek.Foo» para instanciar esa clase. Luego volverá a usar la reflexión para obtener el setter apropiado para el elemento y establecerá su valor en el valor especificado.
El mismo mecanismo también se utiliza para las aplicaciones web de Servlet:
<servlet>
<servlet-name>someServlet</servlet-name>
<servlet-class>com.programcreek.WhyReflectionServlet</servlet-class>
<servlet>
|
someServlet com.programcreek.WhyReflectionServlet
¿Cómo utilizar la reflexión?
Se puede mostrar cómo usar la API de reflexión mediante un pequeño conjunto de ejemplos de código típicos.
Ejemplo 1: obtener el nombre de la clase del objeto
package myreflection;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Foo f = new Foo();
System.out.println(f.getClass().getName());
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
|
paquete myreflection; import java.lang.reflect.Method; public class ReflectionHelloWorld {public static void main (String[] args) {Foo f = new Foo (); System.out.println (f.getClass (). GetName ()); }} class Foo {public void print () {System.out.println («abc»); }}
Producción:
myreflection.Foo
Ejemplo 2: método de invocación en un objeto desconocido
Para el ejemplo de código a continuación, se desconocen los tipos de un objeto. Al usar la reflexión, el código puede usar el objeto y averiguar si el objeto tiene un método llamado «imprimir» y luego llamarlo.
package myreflection;
import java.lang.reflect.Method;
public class ReflectionHelloWorld {
public static void main(String[] args){
Foo f = new Foo();
Method method;
try {
method = f.getClass().getMethod("print", new Class<?>[0]);
method.invoke(f);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
|
paquete myreflection; import java.lang.reflect.Method; public class ReflectionHelloWorld {public static void main (String[] args) {Foo f = new Foo (); Método método; intente {método = f.getClass (). getMethod («imprimir», nueva clase >[0]); método.invocar (f); } captura (Excepción e) {e.printStackTrace (); }}} class Foo {public void print () {System.out.println («abc»); }}
abc
Ejemplo 3: crear un objeto a partir de una instancia de clase
package myreflection;
public class ReflectionHelloWorld {
public static void main(String[] args){
//create instance of "Class"
Class<?> c = null;
try{
c=Class.forName("myreflection.Foo");
}catch(Exception e){
e.printStackTrace();
}
//create instance of "Foo"
Foo f = null;
try {
f = (Foo) c.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
f.print();
}
}
class Foo {
public void print() {
System.out.println("abc");
}
}
|
paquete myreflection; public class ReflectionHelloWorld {public static void main (String[] args) {// crear instancia de «Clase» Clase > c = null; intente {c = Class.forName («myreflection.Foo»); } captura (Excepción e) {e.printStackTrace (); } // crea una instancia de «Foo» Foo f = null; intente {f = (Foo) c.newInstance (); } captura (Excepción e) {e.printStackTrace (); } f.print (); }} class Foo {public void print () {System.out.println («abc»); }}
Ejemplo 4: obtener el constructor y crear una instancia
package myreflection;
import java.lang.reflect.Constructor;
public class ReflectionHelloWorld {
public static void main(String[] args){
//create instance of "Class"
Class<?> c = null;
try{
c=Class.forName("myreflection.Foo");
}catch(Exception e){
e.printStackTrace();
}
//create instance of "Foo"
Foo f1 = null;
Foo f2 = null;
//get all constructors
Constructor<?> cons[] = c.getConstructors();
try {
f1 = (Foo) cons[0].newInstance();
f2 = (Foo) cons[1].newInstance("abc");
} catch (Exception e) {
e.printStackTrace();
}
f1.print();
f2.print();
}
}
class Foo {
String s;
public Foo(){}
public Foo(String s){
this.s=s;
}
public void print() {
System.out.println(s);
}
}
|
paquete myreflection; import java.lang.reflect.Constructor; public class ReflectionHelloWorld {public static void main (String[] args) {// crear instancia de «Clase» Clase > c = null; intente {c = Class.forName («myreflection.Foo»); } captura (Excepción e) {e.printStackTrace (); } // crea una instancia de «Foo» Foo f1 = null; Foo f2 = nulo; // obtener todos los constructores Constructor > contras[] = c.getConstructors (); prueba {f1 = (Foo) contras[0].nueva instancia(); f2 = (Foo) contras[1].newInstance («abc»); } captura (Excepción e) {e.printStackTrace (); } f1.print (); f2.print (); }} clase Foo {String s; public Foo () {} public Foo (String s) {this.s = s; } public void print () {System.out.println (s); }}
Producción:
null
abc
Además, puede usar la instancia de Class para obtener interfaces implementadas, superclase, campo declarado, etc.
Ejemplo 5: cambiar el tamaño de la matriz mediante la reflexión
package myreflection;
import java.lang.reflect.Array;
public class ReflectionHelloWorld {
public static void main(String[] args) {
int[] intArray = { 1, 2, 3, 4, 5 };
int[] newIntArray = (int[]) changeArraySize(intArray, 10);
print(newIntArray);
String[] atr = { "a", "b", "c", "d", "e" };
String[] str1 = (String[]) changeArraySize(atr, 10);
print(str1);
}
// change array size
public static Object changeArraySize(Object obj, int len) {
Class<?> arr = obj.getClass().getComponentType();
Object newArray = Array.newInstance(arr, len);
//do array copy
int co = Array.getLength(obj);
System.arraycopy(obj, 0, newArray, 0, co);
return newArray;
}
// print
public static void print(Object obj) {
Class<?> c = obj.getClass();
if (!c.isArray()) {
return;
}
System.out.println("nArray length: " + Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i) + " ");
}
}
}
|
paquete myreflection; import java.lang.reflect.Array; public class ReflectionHelloWorld {public static void main (String[] argumentos) {int[] intArray = {1, 2, 3, 4, 5}; En t[] newIntArray = (int[]) changeArraySize (intArray, 10); imprimir (newIntArray); Cuerda[] atr = {«a», «b», «c», «d», «e»}; Cuerda[] str1 = (Cadena[]) changeArraySize (atr, 10); imprimir (str1); } // cambiar el tamaño de la matriz public static Object changeArraySize (Object obj, int len) {Class > arr = obj.getClass (). getComponentType (); Objeto newArray = Array.newInstance (arr, len); // hacer una copia de la matriz int co = Array.getLength (obj); System.arraycopy (obj, 0, newArray, 0, co); return newArray; } // imprimir public static void print (Object obj) {Class > c = obj.getClass (); if (! c.isArray ()) {return; } System.out.println (» nLongitud de la matriz:» + Array.getLength (obj)); for (int i = 0; i
Producción:
Array length: 10
1 2 3 4 5 0 0 0 0 0
Array length: 10
a b c d e null null null null null
Resumen
Los ejemplos de código anteriores muestran un conjunto muy pequeño de funciones proporcionadas por la reflexión de Java. La lectura de esos ejemplos solo puede darle una idea de la reflexión de Java, es posible que desee Lea más información en el sitio web de Oracle.
Referencias:
1. http://en.wikipedia.org/wiki/Reflection_(computer_programming)
2. http://docs.oracle.com/javase/tutorial/reflect/