Hola, somos Arume

Desarrollamos páginas web, aplicaciones para móviles, capas de realidad aumentada y aplicaciones para Facebook. Nos apasiona la informática y somos unos perfeccionistas incurables; por eso en nuestros proyectos utilizamos estándares.

tel. 625 519 694

Mendaña de Neyra, 34, 3º B, 15008, A Coruña

Autenticarse

Registrarse. ¿Has olvidado tu contraseña?

Etiquetas

Saltar las etiquetas

Suscríbete a las RSS

Estás en:

Java Reflection (parte 1)

26 Abr 2011 por Santi

Comentarios: 17

Java

Una de las funcionalidades más potentes y poco conocidas de Java es su soporte para reflexión. Mediante la Java Reflection API el programador puede inspeccionar y manipular clases e interfaces (así como sus métodos y campos) en tiempo de ejecución, sin conocer a priori (en tiempo de compilación) los tipos y/o nombres de las clases específicas con las que está trabajando.

Quizás pueda parecernos en una primera impresión una funcionalidad con usos limitados. Pero debemos saber que, por ejemplo, muchos frameworks de alto nivel como Hibernate, Spring o Tapestry hacen un uso extensivo de esta API para facilitarle la vida al programador al permitirle que use simples clases POJO para trabajar con ellas. Otros frameworks menos potentes (o versiones antiguas de estos mismos frameworks), obligaban al programador a que sus clases implementaran ciertos interfaces o pertenecieran a complicadas jerarquías de clases, lo cual limitaba la flexibilidad del programador y complicaba la comprensión del código.

Clase

Cuando en nuestro programa queremos usar reflexión para poder trabajar con un objeto del que desconocemos su tipo (en el caso de Java, esto es lo mismo que decir que desconocemos el nombre de su clase), lo primero que debemos hacer es averiguar la clase a la que pertenece. En situaciones normales conoceremos el tipo de un objeto en tiempo de compilación, con lo que obtendríamos su clase de la forma:

Class userClass = User.class;

En aquellas situaciones en las que no conozcamos el nombre de una clase en tiempo de compilación, podemos obtener su clase en tiempo de ejecución a partir de un String que contenga el nombre completo de la clase (incluyendo los paquetes, lo que se conoce como nombre de clase totalmente calificado) usando la función Class.forName():

Class userClass = Class.forName("com.test.model.AdminUser");

En nuestro ejemplo, la clase es AdminUser que pertenece al paquete com.test.model.

Si por algún motivo la clase no existiese, se lanzaría una excepción ClassNotFoundException para indicarlo.

En sentido inverso, teniendo la clase de un objeto también podremos obtener una cadena con el nombre de la clase:

String className = userClass.getName();

Este ejemplo nos devuelve el nombre totalmente calificado de la clase. Si queremos sólo el nombre simple (sin el paquete), debemos usar el método getSimpleName().

Información adicional

Podemos obtener el paquete de una clase mediante:

Package userPackage = userClass.getPackage();

Nótese que no devuelve un simple String con el nombre del paquete, sino un objeto de tipo Package que contiene información sobre el paquete y métodos para su manipulación.

También podemos acceder a la superclase de una clase (que será nuevamente un objeto Class, de forma que podemos seguir haciendo reflexión sobre él) mediante el método:

Class userSuperclass = userClass.getSuperclass();

Podemos obtener una lista de los interfaces que implementa una clase (en forma de array de objetos Class) mediante:

Class[] userInterfaces = userClass.getInterfaces();

Debe tenerse en cuenta que sólo se incluyen los interfaces implementados directamente por esta clase, no los que se heredan porque son implementados por alguna superclase de la jerarquía.

Constructores

Podemos acceder a la lista de todos los constructores de una clase mediante el método:

Constructor[] userConstructors = userClass.getConstructors();

Si conocemos los tipos de los parámetros de un constructor en particular, podemos acceder a ese constructor concreto sin tener que recorrer toda la lista. Esto se hace mediante el método getConstructor(), que admite como parámetros un array con los tipos específicos de ese constructor (en el mismo orden en el que están declarados). Por ejemplo, si sabemos que nuestra clase de ejemplo contiene un constructor que acepta los parámetros (String, String, Integer) podemos acceder a él mediante:

Constructor userConstructor = userClass.getConstructor(new Class[] {String.class, String.class, Integer.class});

Si no existiera un constructor con esos parámetros, se lanzaría una excepción de tipo NoSuchMethodException.

A la inversa, para un constructor también podemos obtener sus parámetros mediante:

Class[] params = userConstructor.getParameterTypes();

Una vez hallamos conseguido el constructor deseado, podemos instanciar un objeto mediante el método newInstance() con los parámetros adecuados. En nuestro ejemplo:

Constructor userConstructor = userClass.getConstructor(new Class[] {String.class, String.class, Integer.class});
User user = (User) userConstructor.newInstance("Antonio González", "agonzalez@mimail.com", 12);

Puedes leer más sobre este tema en nuestro artículo Java Reflection (parte 2).

Comentarios

17 comentarios. Comentar.

1. Anónimo el 23 Oct 2011 a las 21:23:09

Buena descripcion :-)

2. Anónimo el 04 Dic 2011 a las 05:12:47

muy bien explicado+

3. Anónimo el 09 Dic 2011 a las 05:30:43

Amigos tengo una pregunta mm aver si me ayudan un poco tengo una clase:

public class grid_marca{

public static DefaultTableModel cont_table;

public static JPanel grid_marca(){

//aqui el cuerpo de la tabla

cont_table..................

}

}

luego tengo una segunda clase:

public class Grid {

public void grid(){

grid_marca objeto=new grid_marca()

objeto.cont_table.addRow(fila);

}

}

lo que quiero es que el "grid_marca" sea dinamico(por ejemplo quiero poner grid_venta u otro) y puedo agregar los datos a la tabla de esta segunda clase.

Le agradeciria mucho su respuesta.

4. Anónimo el 04 Oct 2012 a las 21:30:25

Amigos tengo una pregunta mm aver si me ayudan un poco tengo una clase:

public class grid_marca{

public static DefaultTableModel cont_table;

public static JPanel grid_marca(){

//aqui el cuerpo de la tabla

cont_table..................

}

}

luego tengo una segunda clase:

public class Grid {

public void grid(){

grid_marca objeto=new grid_marca()

objeto.cont_table.addRow(fila);

}

}

lo que quiero es que el "grid_marca" sea dinamico(por ejemplo quiero poner grid_venta u otro) y puedo agregar los datos a la tabla de esta segunda clase.

Le agradeciria mucho su respuesta.

---> eso no es este tema.......

6. donKsper el 20 Nov 2012 a las 21:38:22

Excelente aporte... muchas gracias!

7. Anónimo el 11 Ene 2013 a las 15:52:52

Buena explicación

8. osa el 14 Mar 2013 a las 20:29:14

Y que diferencia existe entre getConstructors y getDeclaredConstructors me gustaria saberlo gracias.

9. Luis el 15 Mar 2013 a las 11:57:01

Hola osa.

La diferencia es que getConstructors devuelve sólo los constructores públicos mientras que getDeclaredConstructors devuelve todos los constructores: públicos, privados, ...

Puedes ver más en este enlace: http://stackoverflow.com/questions/8249173/what-is-the-di...

10. Anónimo el 02 Jun 2013 a las 03:26:14

Este blog es hermoso, gracias.

11. Anónimo el 04 Sep 2013 a las 00:16:30

Graxias, excelente aporte

12. E el 21 Ene 2014 a las 15:39:13

Hola, muy buena explicación, pero, ¿Me podrías dar algún ejemplo en dónde se utiliza ? O sea, me explico mejor, en que casos desconocería a que tipo de clase pertenece mi objeto.

Gracias

13. Luis el 22 Ene 2014 a las 11:32:59

Hola E.

Algunos ejemplos son:

- Aplicaciones de "debug" de otras aplicaciones (de las cuales desconoces sus clases).

- Aplicaciones de generación de documentación de código.

- Aplicaciones para generar tablas en base de datos a través de las clases existentes.

Un saludo.

14. Francisco Cruz el 27 Jul 2014 a las 19:35:04

Excelente tutorial. la forma de explicarlo es muy concreta.

15. Luis Fernando Ortiz Vera el 28 Ago 2014 a las 04:31:19

Excelente aporte, muchas gracias!!

16. zapatao el 19 Nov 2014 a las 19:26:49

hola, gracias por tu aporte me sirvio de mucho.

Quisiera hacer una pregunta : si yo se el nombre de una clase que esta en otro paquete y no deseo poner toda la ruta(package) cuando lo invoque con el Class.forName, hay alguna funcion que me devuelva un package generico que busque en todos los paquetes hasta encontrar la clase??.

17. mario el 17 May 2015 a las 23:14:06

Muchisimas gracias por tu tutorial, desconocia esta parte de Java de como implementarla, y en este momento me preguntaba como hacer algo así.

Me haz ilustrado bastante y ayudado.

Mil gracias.

18. Carlos Arturo el 25 Abr 2016 a las 23:21:56

Excelente tutorial...Esta parte es importante para para la busqueda de clases y objetos...Muchas Gracias.

Comentar

Comentar de forma anónima

Puedes comentar poniendo cualquier nombre o apodo, exceptuando los nombres de usuarios registrados. Máximo de 50 caracteres.

Comentar como usuario registrado

Registrarse. ¿Has olvidado tu contraseña?