Reflexión en Java III, Acceso y modificación de propiedades

Continuando con mi aportación para el CPJ y mi exposición de reflexión en java. En el post anterior mostré como obtener las propiedades de una clase, ahora veremos cómo colocar valores y obtener los valores almacenados en las propiedades de un objeto de una clase desconocida, recuerden que la reflexión solo nos permite acceso a los recursos públicos de las clases.

Para iniciar nuevamente modifico un poco las cases que nuestro programa observará mediante reflexión

A.java

/**
 *
 * @author jfcodiaz
 * wariodiaz@gmail.com
 * <a href="http://www.devtics.com.mx
" title="www.devtics.com.mx
">www.devtics.com.mx
</a> * 17/04/2010
 */

public class A {
    public int n1;
    public int R;
    public int n2;
    public String nombre;
    public B b;
    @Override
    public String toString() {
        return "Esto es una clase A";
    }
    public void saludo(){
        System.out.println("Hola Mundo!");
    }
}

B.java

/**
 *
 * @author jfcodiaz
 * wariodiaz@gmail.com
 * <a href="http://www.devtics.com.mx
" title="www.devtics.com.mx
">www.devtics.com.mx
</a> * 15/04/2010
 */

public class B {
    public String propiedad1;
    public String propiedad2;
    @Override
    public String toString() {
        return "esto es una B";
    }    
}

Solo he cambiado el acceso a R, en B a publico esto porque el objetivo de este post es mostrar el acceso, asignación y recuperación de las propiedades de una clase a través de reflexión lo cual solo se puede realizar con propiedades públicas.

Como vimos en el post anterior podemos saber el tipo de dato que almacena una determinada propiedad a través de objField.getType() el cual nos retornara un objeto Class el cual de igual forma podremos analizar si vamos al método .toString() del objeto devuelto podremos ver que nos retorna una cadena con el tipo de dato si este es nativo(int, short, boolean, char, float, double, byte, long) o bien la cadena “class”, un espacio y el nombre completo de la clase en el classPath (esto se vio en el ejemplo anterior)

La clase Class nos permite obtener su nombre con objClass.getName() el cual nos retorna el nombre de la clase o su ruta en el classpath al igual que si se trata de un tipo nativo el tipo de dato, con esto podremos crear un programa que analice la clase e identificar qué tipo de dato debemos colocar en cada una de las variables.

Para colocar un valor los objetos Field (java.lang.reflect.Field) cuentan con los siguientes métodos de los cuales sus nombres son muy descriptivos.

- set(Object obj, Object value) void
- setBoolean(Object obj, boolean z) void
- setByte(Ojbect obj, byte b) void
- setChar(Object obj, char c) void
- setDouble(Object obj, double d) void
- setFloat(Object obj, float f) void
- setInt(Object obj, int i) void
- setLong(Object obj, long l) void
- setShort(Object obj, short s) void

El primer primer parámetro es el objeto en el que se buscara la propiedad y se le asignara el valor del Segundo parámetro, los setter son para los tipos de datos nativos, para propiedades que sean objetos se utiliza el método set().

Para recuperar los datos utilizamos los siguientes métodos getters de los objetos Field también muy descriptivos

-get(Object obj) Object
-getBoolean(Object obj) boolean
-getByte(Object obj) byte
-betChar(Object obj) char
-getDouble(Object obj)double
-getFloat(Object obj) float
-getInt(Object ojb) int
-getLong(Object obj) long
-getShort(Object obj) short

El único parámetro es el objeto donde se buscará la propiedad y de igual forma se utiliza cada getter segun el tipo de dato una vez si es que se sabe el tipo de dato que se obtendrá si no puede utilizar el método get y luego analizar el objeto para saber que tipo de dato es, todos los objetos en java tienen el método .getClass() el cual nos retorna un objeto Class con clase del objeto

Por ultimo dejo un ejemplo donde se analiza crea un objeto de una clases desconocida y si se encuentran propiedades String o int se llama a su setter y posteriormente se muestra el valor de todos los atributos de un objeto de la clases indicada por ultimo el programa nos pregunta el nombre de una propiedad para conocer su valor.

import java.lang.reflect.Field;
import java.util.Scanner;
/**
 *
 * @author jfcoDiaz
 * <a href="http://www.devtics.com.mx
" title="www.devtics.com.mx
">www.devtics.com.mx
</a> * 18/04/2010
 *
 */

public class Reflexion3 {
    public static void main(String[] args) {
        String nombreClase = "";
        Class _class;
        Object obj;
        Scanner sc = new Scanner(System.in);
        Field[] propieties;
        try {
            nombreClase =  sc.nextLine();
            _class = Class.forName(nombreClase);
            obj = _class.newInstance();
            propieties = _class.getFields();
            for (int i = 0; i < propieties.length; i++) {
                Field field = propieties[i];

                String nameType = field.getType().getName();
                if (nameType.equals("int")) {
                    System.out.println("Escribe El Valor  que guardara en "+field.getName()+" (Solo Numeros Enteros) " );
                    field.set(obj, Integer.parseInt(sc.nextLine()));
                } else if (nameType.equals("B")) {
                    field.set(obj, new B());
                } else if (nameType.equals("java.lang.String")) {
                    System.out.println("Escribe El Valor que guardara " + field.getName());
                    field.set(obj, sc.nextLine());
                } else {
                    System.out.println("Este programa no soporta la asignacion de " + nameType);
                }
            }
            for (int i = 0; i < propieties.length; i++) {
                Field field = propieties[i];
               
                System.out.println(field.getName() + " vale " + field.get(obj).toString());
            }
            System.out.println("Escribe el nombre de una propiedad para conocer su valor");
            Field field = _class.getField(sc.nextLine());
            System.out.println("La Propiedad " + field.getName() + " vale " + field.get(obj).toString());
        } catch (InstantiationException ex) {
            System.out.println("Error al Crear el Objeto");
        } catch (IllegalAccessException ex) {
            System.out.println("Error al Crear el Objeto");
        } catch (ClassNotFoundException ex) {
            System.out.println("La " + nombreClase + " Clase Indicada no Existe en el ClassPath");
        } catch (NoSuchFieldException ex) {
            System.out.println("El objeto no cuenta con la propiedad indicada");
        } catch (SecurityException ex) {
            System.out.println("No se tiene acceso a la clase o propiedad");
        }
    }
}

Con esto ya he mostrado como analizar una Clase y obtener sus propiedades . crear un objeto de esta clase desconocida e interactuar con sus propiedades, en el siguiente post mostrare como conocer los métodos de una clase mediante reflexión.

Códigos Fuentes de ejemplos en Netbeans 6.8

<< Aportación JavaMéxico - PCJ - Reflexión en Java I, Instancia una clase desconocidas en tiempo de ejecución
<< Reflexión en Java II, Obtener propiedades de una clase desconocidas en tiempo de ejecución

www.devtics.com.mx