Ola, somos Arume

Desenvolvemos páxinas web, aplicacións para móbiles, capas de realidade aumentada e aplicacións para Facebook. Apaixónanos a informática e somos uns perfeccionistas incurables; por eso nos nosos proxectos utilizamos estándares.

tel. 625 519 694

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

Autenticarse

Rexistrarse. Esqueceches o teu contrasinal?

Etiquetas

Saltar as etiquetas

Subscríbete ás RSS

Estás en:

Java Reflection (parte 1)

26 Abr 2011 por Santi

Comentarios: 17

Java

Unha das funcionalidades máis potentes e pouco coñecidas de Java é o seu soporte para reflexión. Mediante a Java Reflection API o programador pode inspeccionar e manipular clases e interfaces (así como os seus métodos e campos) en tempo de execución, sen coñecer a priori (en tempo de compilación) os tipos e/ou nomes das clases específicas cas que está traballando.

Quizais poida parecernos nunha primeira impresión unha funcionalidade con usos limitados. Pero debemos saber que, por exemplo, moitos frameworks de alto nivel como Hibernate, Spring ou Tapestry fan un uso extensivo desta API para facilitarlle a vida ó programador ó permitirlle que use simples clases POJO para traballar con elas. Outros frameworks menos potentes (ou versións antigas destes mesmos frameworks), obrigaban ó programador a que as súas clases implementaran certos interfaces ou pertencesen a complicadas xerarquías de clases, o cal limitaba a flexibilidade do programador e complicaba a comprensión do código.

Clase

Cando no noso programa queremos usar reflexión para poder traballar cun obxecto do que descoñecemos o seu tipo (no caso de Java, isto é o mesmo que dicir que descoñecemos o nome da súa clase), o primeiro que debemos facer é pescudar a clase á que pertence. En situacións normais coñeceremos o tipo dun obxecto en tempo de compilación, co que obteriamos a súa clase da forma:

Class userClass = User.class;

Naquelas situacións nas que non coñezamos o nome dunha clase en tempo de compilación, podemos obter a súa clase en tempo de execución a partir dun String que conteña o nome completo da clase (incluíndo os paquetes, o que se coñece como nome de clase totalmente cualificado) usando a función Class.forName():

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

No noso exemplo, a clase é AdminUser que pertence ó paquete com.test.model.

Se por algún motivo a clase non existise, lanzaríase unha excepción ClassNotFoundException para indicalo.

En sentido inverso, tendo a clase dun obxecto tamén poderemos obter unha cadea co nome da clase:

String className = userClass.getName();

Este exemplo devólvenos o nome totalmente cualificado da clase. Se queremos só o nome simple (sen o paquete), debemos usar o método getSimpleName().

Información adicional

Podemos obter o paquete dunha clase mediante:

Package userPackage = userClass.getPackage();

Nótese que non devolve un simple String co nome do paquete, senón un obxecto de tipo Package que contén información sobre o paquete e métodos para a súa manipulación.

Tamén podemos acceder á superclase dunha clase (que será novamente un obxecto Class, de forma que podemos seguir facendo reflexión sobre el) mediante o método:

Class userSuperclass = userClass.getSuperclass();

Podemos obter unha lista dos interfaces que implementa unha clase (en forma de array de obxectos Class) mediante:

Class[] userInterfaces = userClass.getInterfaces();

Debe terse en conta que só se inclúen os interfaces implementados directamente por esta clase, non os que se herdan porque son implementados por algunha superclase da xerarquía.

Constructores

Podemos acceder á lista de todos os construtores dunha clase mediante o método:

Constructor[] userConstructors = userClass.getConstructors();

Se coñecemos os tipos dos parámetros dun construtor en particular, podemos acceder a ese construtor concreto sen ter que percorrer toda a lista. Isto faise mediante o método getConstructor(), que admite como parámetros un array cos tipos específicos dese construtor (no mesmo orde no que están declarados). Por exemplo, se sabemos que a nosa clase de exemplo contén un construtor que acepta os parámetros (String, String, Integer) podemos acceder a el mediante:

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

Se non existise un construtor con eses parámetros, lanzaríase unha excepción de tipo NoSuchMethodException.

Á inversa, para un construtor tamén podemos obter os seus parámetros mediante:

Class[] params = userConstructor.getParameterTypes();

Unha vez consigamos o construtor desexado, podemos instanciar un obxecto mediante o método newInstance() cos parámetros adecuados. No noso exemplo:

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

Podes ler máis sobre este tema no noso artigo Java Reflection (parte 2).

Comentarios

17 comentarios. Comentar.

1. Anónimo o 23 Out 2011 ás 21:23:09

Buena descripcion :-)

2. Anónimo o 04 Dec 2011 ás 05:12:47

muy bien explicado+

3. Anónimo o 09 Dec 2011 ás 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 o 04 Out 2012 ás 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 o 20 Nov 2012 ás 21:38:22

Excelente aporte... muchas gracias!

7. Anónimo o 11 Xan 2013 ás 15:52:52

Buena explicación

8. osa o 14 Mar 2013 ás 20:29:14

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

9. Luis o 15 Mar 2013 ás 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 o 02 Xuñ 2013 ás 03:26:14

Este blog es hermoso, gracias.

11. Anónimo o 04 Set 2013 ás 00:16:30

Graxias, excelente aporte

12. E o 21 Xan 2014 ás 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 o 22 Xan 2014 ás 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 o 27 Xul 2014 ás 19:35:04

Excelente tutorial. la forma de explicarlo es muy concreta.

15. Luis Fernando Ortiz Vera o 28 Ago 2014 ás 04:31:19

Excelente aporte, muchas gracias!!

16. zapatao o 19 Nov 2014 ás 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 o 17 Mai 2015 ás 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 o 25 Abr 2016 ás 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

Podes comentar poñendo calquera nome ou alcume, exceptuando os nomes de usuarios rexistrados. Máximo de 50 caracteres.

Comentar como usuario rexistrado

Rexistrarse. Esqueceches o teu contrasinal?