La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

CJ02 – Técnicas avanzadas en java 1.4 y 5.0

Presentaciones similares


Presentación del tema: "CJ02 – Técnicas avanzadas en java 1.4 y 5.0"— Transcripción de la presentación:

1 CJ02 – Técnicas avanzadas en java 1.4 y 5.0
Parte 2 – reflection en java 5.0

2 Objetivos generales Introducción Características de la API
Examinando clases (java.lang.Class) Manipulación de instancias Instanciación Manipulación de atributos Invocación de métodos Sumario

3 Introducción Java posee la capacidad de introspección o “reflection”
Mecanismo para descubrir en tiempo de ejecución la información (meta-datos) relacionada con los atributos, constructores y métodos de una clase Una de las funcionalidades más potentes y poco conocidas de Java es su soporte para reflection. Utilizando la librería Java Reflection API, java nos permite inspeccionar y manipular clases e interfaces en tiempo de ejecución, sin conocer a priori los tipos y nombres de las clases específicas con las que está trabajando.

4 Características de la API
La API permite: Determinar la clase de un objeto Obtener información acerca de Modificadores Atributos Métodos Constructores Superclases. Descubrir las constantes y declaraciones de métodos de una interface También nos permite: Crear una instancia de una clase cuyo nombre es desconocido hasta el momento de la ejecución Obtener y setear valores a atributos de un objeto, incluso si el nombre del atributo no se conoce hasta el momento de la ejecución Invocar un método sobre un objeto, incluso si el nombre del método no se conoce hasta el momento de la ejecución Crear un nuevo array, cuyo tamaño y el tipo de sus contenidos no se conocen hasta el momento de la ejecución, y modificar sus componentes

5 Examinando clases (java.Lang.Class)
Situación: A veces es necesario obtener información de una clase en tiempo de ejecución Ejemplo: class browser Un objeto de tipo java.lang.Class representa (refleja) una clase. La JVM mantiene un objeto inmutable de este tipo para cada clase Como todos los objetos heredan de la clase java.lang.Object, poseen el método getClass(), el cual nos devuelve un objeto de tipo java.lang.Class. Ahora bien, entre sus métodos encontramos: java.lang.Class forName(String className): Método que carga una clase a partir de su nombre. Si ocurre un error, como ser que no se encontró la clase se lanza una excepción de tipo java.lang.ClassNotFoundException. java.lang.reflect.Field getField(String name): Retorna un atributo público de la clase a partir de su nombre. Si la clase no contiene ningún campo con ese nombre, se comprueban sus superclases recursivamente, y en caso de no encontrar finalmente el campo, se lanzará la excepcion java.lang.NoSuchFieldException. java.lang.reflect.Field[] getFields(): Devuelve un array con todos los campos públicos de la clase, y de sus superclases. java.lang.reflect.Method getMethod(String name, Class[] parameterTypes): Devuelve un método público de la clase, a partir de su nombre, y de un array con las clases de los parámetros del método. Si la clase no contiene ningún método con ese nombre y esos parámtetros, se lanzará la excepcion java.lang.NoSuchMethodException. java.lang.reflect.Method[] getMethods(): Devuelve un array con todos los métodos públicos de la clase, y de sus superclases. java.lang.Class[] getInterfaces(): Devuelve un array con todos los interfaces que implementa la clase.

6 Ejemplos: Prueba.java Class[] types = new Class[] { String.class, String.class }; //defino dos tipos Constructor cons = TwoString.class.getConstructor(types); //obtengo el constructor de dicha clase Object[] args = new Object[] { "a", "b" }; TwoString ts = (TwoString)cons.newInstance(args);//creo una nueva instancia de tipo TwoStrings, haciendo uso del constructor, mediante el uso del método newInstance. Object newInstance() – Crea una nueva instancia usando el constructor por defecto Una factory, es una fábrica de objetos. Este concepto surge en los patrones de diseño creacionales. Basicamente, la idea es tener una clase la cual tenga la responsabilidad de crear objetos de diferentes tipos según un criterio específico. Ejemplo: public static class Factory{ public static Object createObject(int tipo){ if(tipo ==1) return new Customer(); if(tipo ==2) return new Employee(); return null; } Ejemplos En este caso, veremos ejemplos de la creación de objetos de tipo TwoString mediante Reflection. La clase TwoString esta dada por: TwoString.java public class TwoString { private String m_s1, m_s2; public TwoString(String s1, String s2) { m_s1 = s1; m_s2 = s2; }

7 Obtención del objeto class
Sobre una instancia (método getClass de Object) Class c = myObject.getClass(); Superclases ¿Como obtengo el descriptor de la clase Vehiculo que es superclase de Automovil? Automovil a = new Automovil(); Class c = a.getClass(); Class superclase = c.getSuperclass(); Si el nombre de la clase se conoce en tiempo de compilación Class c = java.awt.Button.class; Si el nombre se conoce en tiempo de ejecución (método estático forName de la clase Class) String nombreClase = …; Class c = Class.forName(nombreClase); Ejemplo: implementación de factories concretas configurables. En patrones de diseño, encontramos el concepto de factory o fábrica el cual se utiliza para creación de objetos. Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar las clases concretas de las que son instancia.

8 Obteniendo información de una clase nombre de la clase
Método String getName() import java.lang.reflect.*; import java.util.*; public class TestClassName { public static void main(String[] args) { Date now = new Date(); printClassName(now); } static void printClassName(Object o) { Class c = o.getClass(); String s = c.getName(); System.out.println(s); } } En el ejemplo anterior, imprime “java.util.Date” en la salida estándar, dado que el objeto es de tipo Date. En este caso, se crea un objeto de tipo Date, de manea de que al utilizar los métodos proporcionados por java.lang.reflect, podamos obtener la clase de dicho objeto y su nombre utilizando los métodos: Class c = o.getClass(); String s = c.getName(); En este ejemplo, se intenta obtener información de una clase, como ser> el nombre de la misma.

9 Obteniendo información de una clase modificadores
import java.lang.reflect.*; import java.awt.*; public class TestModifiers { public static void main(String[] args) { String s = new String(); printModifiers(s); } public static void printModifiers(Object o) { Class c = o.getClass(); int m = c.getModifiers(); if (Modifier.isPublic(m)) System.out.println("public"); if (Modifier.isAbstract(m)) System.out.println("abstract"); if (Modifier.isFinal(m)) System.out.println("final"); } } En este ejemplo, se intenta obtener información de una clase. Particularmente, los modificadores de la misma y sus características. Dado el código anterior, qué se imprime? Public //dado que los modificadores son públicos Final //dado que la clase es final, por lo que no puede ser extendida. En este ejemplo, se intenta ver cómo son utilizados los métodos de java.lang.reflect. Para ello se obtiene la clase del objeto String (Class c = o.getClass();) y se obtienen sus modificadores. Si estos son públicos, abstractos o final (no pueden ser heredados), se imprimirá cierto valor. Como vemos, uno de ellos resultó ser públic y otro final.

10 Obteniendo información de una clase superclase
import java.lang.reflect.*; import java.awt.*; class SampleSuper { public static void main(String[] args) { Button b = new Button(); printSuperclasses(b); } static void printSuperclasses(Object o) { Class subclass = o.getClass(); Class superclass = subclass.getSuperclass(); while (superclass != null) { String className = superclass.getName(); System.out.println(className); subclass = superclass; superclass = subclass.getSuperclass(); } } } Método Class getSuperclass(): Qué imprime? java.awt.Component java.lang.Object Dado que la clase padre directa es awt.Component, la cual hereda de la clase Objetct.

11 Obteniendo información de una clase examinando interfaces
Método boolean isInterface() Obtener las constantes primitivas públicas definidas en la interface: Field [] getFields() Obtener los métodos públicos declarados en la interface: Method [] getMethods() Vamos a ver un ejemplo de como utilizar de algunos de esos métodos. Primero, necesitamos una clase sobre la que vamos a trabajar, como puede ser la siguiente. public class EjemploBean { public String nombre = "Keko"; private String = private void setNombre(String s) { nombre = s; }  protected String getNombre() { return nombre; }  public void set (String s) { = s; }  public String get () { return ; } }  

12 Obteniendo información de una clase examinando interfaces
Como ya hemos dicho antes, los métodos de la API Reflection nos permiten acceder a los campos y métodos públicos (por eso no aparecen , getNombre y setNombre) y los métodos hashCode, getClass, etc. son métodos de la clase java.lang.Object, de la que hereda nuestra clase. En este caso, veremos un ejemplo en el cual se obtiene información de una clase como ser: métodos y campos, Veamos un ejemplo: import java.lang.reflect.*; public class EjemploReflection {   public static void main(String arg[]) {   Class clase; Field campo, campos[]; Method metodo, metodos[]; try { // Cargamos la clase clase = Class.forName("EjemploBean");   // Recorremos los campos System.out.println("Lista de campos:\n"); campos = clase.getFields(); for (int i=0; i < campos.length; i++) { campo = campos[i]; System.out.println("\t" + campo.getName()); } // Recorremos los metodos System.out.println("\nLista de metodos:\n"); metodos = clase.getMethods(); for (int i=0; i < metodos.length; i++) { metodo = metodos[i]; System.out.println("\t" + metodo.getName()); } catch (ClassNotFoundException e) { System.out.println("No se ha encontrado la clase. " + e);

13 Ejemplo - Reflection A continuación veremos un ejemplo en el cual utilizaremos algunos de los métodos que nos proporciona la API de Reflection. Dentro del ejemplo, se crea una instancia de una clase en tiempo de ejecución, se obtiene información de los métodos de dicha clase y atributos

14 Ejemplo - Reflection equals notify notifyAll toString
Luego de ejecutar el código del ejemplo anterior, se obtiene: Lista de campos  nombre  Lista de métodos  set get hashCode getClass wait equals notify notifyAll toString

15 Ejemplo - Reflection Reflection, también nos permite obtener información de los constructores. A continuación veremos un ejemplo de cómo crear instancias de objetos en tiempo de ejecución, pudiendo seleccionar que constructor utilizar. Obteniendo información de una clase descubriendo constructores Métodos Constructor [] getConstructors() y Constructor [] getDeclaredConstructors() import java.lang.reflect.*; import java.awt.*; public class SampleConstructor { public static void main(String[] args) { Rectangle r = new Rectangle(); showConstructors(r); } static void showConstructors(Object o) { Class c = o.getClass(); Constructor[] theConstructors = c.getConstructors(); for (int i = 0; i < theConstructors.length; i++) { System.out.print("( "); Class[] parameterTypes = theConstructors[i].getParameterTypes(); for (int k = 0; k < parameterTypes.length; k ++) { String parameterString = parameterTypes[k].getName(); System.out.print(parameterString + " "); } System.out.println(")"); } } }

16 Obteniendo información de una clase información de métodos
Métodos propios y heredados Method [] getMethods() Nuevos métodos declarados en la clase Method [] getDeclaredMethods() Un objeto de tipo Method puede usarse para obtener: Nombre del método Tipo de retorno Tipos de los parámetros Conjunto de modificadores Conjunto de excepciones declaradas Un objeto de tipo Method provee la operación invoke para invocar el método que representa La clase java.lang.reflect.Method, podemos encontrar, entre otros, los siguientes métodos. public String getName(): Devuelve el nombre del método. public Class[] getParameterTypes(): Devuelve un array con las clases de los parámetros del método. public Class[] getExceptionTypes(): Devuelve un array con las clases de las excepciones que puede lanzar el método. public Class getReturnType()): Devuelve la clase del valor que devuelve el método. public Object invoke(Object obj, Object[] args): Ejecuta el método sobre un objeto, pasándole los parámetros necesarios, y devuelve su resultado.

17 Obteniendo información de una clase información de atributos
Propios y heredados Método Field [] getFields() Los declarados a nivel de la clase Método Field [] getDeclaredFields() Si miramos en la API de Reflection, la clase java.lang.reflect.Field podemos ver muchos métodos que nos van a permitir acceder a los campos de una clase, acceder a su valor en un objeto determinado, e incluso modificar su valor.: public String getName(): Devuelve el nombre del campo. public Class getType(): Devuelve la clase del campo. public Object get(Object obj): Devuelve el valor del campo en un objeto. public void set(Object obj, Object value): Asigna un valor al campo en un objeto.

18 Manipulación de instancias instanciación
Para usar el constructor sin argumentos Método Object newInstance() de la clase Class Class c = …; Object o = c.newInstance(); Para usar constructores con argumentos Método Object newInstance() de la clase Constructor // Obtengo el constructor Constructor cons = …; Object o = cons.newInstance(); Declaran la excepción NoSuchMethodException Veamos un ejemplo muy simple: public class constructor2 { public constructor2() { } public constructor2(int a, int b) { System.out.println("a = " + a + " b = " + b); } public static void main(String args[]) { try { Class cls = Class.forName("constructor2"); Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Constructor ct = cls.getConstructor(partypes); Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = ct.newInstance(arglist); } catch (Throwable e) { System.err.println(e); } } }

19 Manipulación de instancias instanciación
En un principio, se establece el tipo de dichos parámetros y se obtiene su constructor: Class cls = Class.forName("constructor2"); Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE; partypes[1] = Integer.TYPE; Constructor ct = cls.getConstructor(partypes); Luego, se crea el objeto pasando los valores correspondientes: Object arglist[] = new Object[2]; arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = ct.newInstance(arglist); En el ejemplo anterior, se crea un objeto de tipo constructor2, utilizando el método getConstructor y newInstance. En este caso, se pasan por parámetro los valores correspondientes para el constructor2 que recibe dos enteros.

20 Manipulación de instancias manipulación de atributos
Recuperación del valor de un atributo primitivo Métodos getXXX sobre las instancias de la clase Field Ejemplo (f de tipo Field, obj objeto a consultar): int i = f.getInt(obj); Recuperación del valor de un atributo objeto Método get sobre las instancias de la clase Field Ejemplo (f de tipo Field, obj objeto a consultar): Object i = f.get(obj); Se aplican las reglas definidas por los modificadores! Ejemplo: import java.lang.reflect.*; public class field2 { public double d; public static void main(String args[]) { try { Class cls = Class.forName("field2"); //obtenemos la clase Field fld = cls.getField("d"); //obtenemos el atributo denominado d field2 f2obj = new field2(); System.out.println("d = " + f2obj.d); fld.setDouble(f2obj, 12.34); //asignamos su valor en 12,34 } catch (Throwable e) { System.err.println(e); } } }   En este objeto, estamos intentando acceder mediante reflection, a los atributos de una clase.

21 Manipulación de instancias manipulación de atributos
Establecer el valor de un atributo primitivo Métodos setXXX sobre las instancias de la clase Field Ejemplo (f de tipo Field, obj objeto a modificar): f.setBoolean(obj, true); Establecer el valor de un atributo objeto Método set sobre las instancias de la clase Field Ejemplo (f de tipo Field, obj objeto a modificar): f.set(obj, new Date()); Se aplican las reglas definidas por los modificadores! En el ejemplo anterior, vimos como establecer el valor a un tipo primitivo: try { Class cls = Class.forName("field2"); //obtenemos la clase Field fld = cls.getField("d"); //obtenemos el atributo denominado d field2 f2obj = new field2(); System.out.println("d = " + f2obj.d); fld.setDouble(f2obj, 12.34); //asignamos su valor en 12,34 Lo cual es análogo para los objetos, solo que se utiliza el método set.

22 Manipulación de instancias invocación de métodos
Obtener el objeto Method asociado al método a invocar Invocar el método Object invoke(Object target, Object [] args) “target” es la instancia sobre la que se invocará el método Ejemplo: public class method2 { public int add(int a, int b) { return a + b; } public static void main(String args[]) { try { Class cls = Class.forName("method2");//creamos la clase de tipo method2 Class partypes[] = new Class[2]; partypes[0] = Integer.TYPE;//creamos los tipos de los argumentos del constructor partypes[1] = Integer.TYPE;//creamos los tipos de los argumentos del constructor Method meth = cls.getMethod("add", partypes); //obtenemos el método a ejecutar por su nombre method2 methobj = new method2();//creamos un objeto de tipo method2 Object arglist[] = new Object[2];//definimos los valores a ser pasados por parámetro arglist[0] = new Integer(37); arglist[1] = new Integer(47); Object retobj = meth.invoke(methobj, arglist);//invocamos el método add, de la clase method2, con los parámetros del array. Integer retval = (Integer)retobj;/hacemos el casteo del retorno a integer. System.out.println(retval.intValue());//imprimimos el resultado } catch (Throwable e) {System.err.println(e); } } }

23 Inclusiones en java 1.5 Se modifica la API de reflection para dar soporte a argumentos variables Class.getMethod Method.invoke Constructor.newInstance Proxy.getProxyClass MessageFormat.format En versiones de Java 1,5, se ha modificado reflection para que se puedan utilizar argumentos variables. Es por ello, que la creación de instancias utilizando reflection no requiere el pasaje de todos los argumentos, sino que el método GetMethod, puede recibir una lista de parámetros variables. Cuándo utilizar argumentos variables? Sólo deben utilizarse cuando se obtiene un beneficio que vale la pena, no se debe sobrecargar un método de argumentos variables, dado que será dificil luego saber que sobrecarga es llamada.

24 resumen Qué es Reflection? Para qué sirve? java.lang.Class
java.lang.reflect.Constructor java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Modifier java.lang.Object java.lang.Class Representa, o refleja, clases e interfaces Permite la instanciación dinámica java.lang.reflect.Constructor Provee información sobre, y accede a, los constructores de una clase java.lang.reflect.Field Provee información acerca de, y accede dinámicamente a,un campo de una clase o interface java.lang.reflect.Method Provee información de, y accede a, un método de una clase o interface Permite la invocación dinámica java.lang.reflect.Modifier Provee métodos estáticos y constantes que permiten obtener información sobre los modificadores de una clase y sus miembros java.lang.Object Provee el método getClass

25 Bibliografía The Java Tutorial Trail de reflection


Descargar ppt "CJ02 – Técnicas avanzadas en java 1.4 y 5.0"

Presentaciones similares


Anuncios Google