Вы находитесь на странице: 1из 4

Reflection: El lado oscuro de la programacin

La API Reflection nos permite acceder a lo que la buena programacin orientada a objetos nos ha ocultado: las estructuras internas de los objetos que manejamos. As, con Reflection, podemos saber la clase de un objeto, sus mtodos, sus atributos Entre las operaciones que podemos realizar se encuentran: cambiar los valores de atributos privados, invocar a mtodos por su nombre, etc. Reflection se utiliza mucho en debuggers o navegadores navegador de clases. Como bien advierte la documentacin oficial de Java, Java utilizar Reflection conlleva una serie de riesgos y problemas. De rendimiento, de seguridad. Porque utilizar Reflection conlleva pasarse por el forro (casi) todos los principios de la Programacin Orientada a Objetos y un cero en cualquier examen de programacin serio, pero tambin es cierto que, utilizndolo de manera correcta y con responsabilidad, se pueden conseguir conseguir algunas cosas muy chulas que de otra manera seran imposibles.

Class, Method, Field


Antes de entrar en el cdigo, un pequeo diagrama con las clases principales de Reflection:

Tenemos tres clases principalmente:

Class, , representando una clase. Que contiene: Field, , representando un atributo, y Method, , representando un mtodo.

Veamos un ejemplo sencillo. Definamos la siguiente clase:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

import java.util.List; import javax.swing.JButton; public class MyClassToBeViolated { private int integerX; private String aString; public Double d; public char getAChar(int i, Object object) { return 'a'; } public Object getAnObject(String string, List<JButton> list) { return null; } }

Hemos puesto algunos atributos y un par de mtodos, para a continuacin, utilizando Reflection, explorarlos. Nos hacemos un main sencillo para probar:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

import java.lang.reflect.Field; import java.lang.reflect.Method; public class Main { public static void main(String args[]) { MyClassToBeViolated object = new MyClassToBeViolated(); Class<?> clazz = object.getClass(); System.out.println("Nombre de la clase: " + clazz.getName()); System.out.println("Que tiene los siguientes atributos:"); for (Field f : clazz.getDeclaredFields()) { System.out.println(f.getName() + " que es de la clase " + f.getType().getName()); } System.out.println( "Y los siguientes mtodos:"); for (Method m : clazz.getDeclaredMethods()) { System.out.println(m.getName()); for (Class<?> c : m.getParameterTypes()) { System.out.println(" tiene un parmetro de la clase c.getName()); } } } }

Y al ejecutar obtenemos:

1 2 3 4 5 6 7 8 9 10 11 12

Nombre de la clase: MyClassToBeViolated Que tiene los siguientes atributos: integerX que es de la clase int aString que es de la clase java.lang.String d que es de la clase java.lang.Double Y los siguientes mtodos: getAChar tiene un parmetro de la clase int tiene un parmetro de la clase java.lang.Object getAnObject tiene un parmetro de la clase java.lang.String tiene un parmetro de la clase java.util.List

Y obtenemos informacin literal sobre la clase que hemos definido. Reflection es una herramienta poderosa, pero aqu vamos a ceirnos slo a la funcionalidad que se requiera para nuestras animaciones.

Ejecutar un Class/Jar desde una aplicacin Java


Hace no mucho se me plante en un proyecto la necesidad de ejecutar una clase (dentro de un jar) que estaba fuera del classpath de la aplicacin. El caso era que la aplicacin tenia que poder ejecutar un mtodo concreto de una clase incluida dentro de un jar que no exista en el momento de iniciar la aplicacin. A parte de provocarme algn dolor de cabeza, esto me mostr claramente como funcionan los ClassLoader en java. Lo voy a comentar porque me parece muy didctico. // Ruta al fichero jar o class File miClass = new File ("path/al/fichero"); // Recupero las url del nuevo classpath URL[] urls = new URL [] {miClass.toURL() }; // Y creo un classLoader ClassLoader loader = this.getClass().getClassLoader(); URLClassLoader nuevoLoader = new URLClassLoader (urls,loader); // Ahora solo debo solicitar la clase al nuevo classLoader e instanciarla Class clase = nuevoLoader .loadClass("paquete.Clase"); Object instancia = clase.newInstance(); // Y ya la usamos con reflexin. Class[] args = new Class [] {}; // Configuramos try { Method metodo = clase.getMethod("metodo", args); metodo.invoke(instancia, new Object[] {}); } ... As es como yo lo hice, no digo que sea la mejor manera, pero al menos funcion. Otra opcin es usar el mtodo "defineClass", que es protegido, pero que permite cargar la clase dentro del classloader actual. Echndole un vistazo a esta pgina se ve una solucion pero parece que solo vale para un fichero ".class".
Escrito por Fernando Rosado Altamirano Enviar por correo electrnicoEscribe un blogCompartir con TwitterCompartir con Facebook

Te ha parecido:

a las martes, febrero 05, 2008

5 comentarios:
Annimo dijo... Hola Estamos haciendo un proyecto sobre la reflexion y tenemos un problema para cargar las clases externas al classpath. Hemos visto la solucion que propones y la tenemos

similar salvo una linea ClassLoader loader = this.getClass().getClassLoader(); No entendemos mmuy bien esta linea Como se llama la clase donde ejecutas el ClassLoader? Si nos puedes mandar tu classLoader te lo agradeceriamos mucho pues estamos estancados en el proyecto. Un Saludo perla y gracias 22/04/08 17:49

Guevonaso dijo... Esta es una clase cualquiera, no tengo definido ningun ClassLoader, el ejemplo era muy simple y para mi caso concreto funcion, pero no pude hacer pruebas exaustivas. La case era tan simple como : class MIClase { .... public void ejecuta() { // El codigo de arriba } public static void main(String[] args) { new MiClase ().ejecuta(); }}

De esta forma uso el "this".

Вам также может понравиться