2008-11-09 18 views
11

Estoy mirando para poner en práctica algo en Java lo largo de las líneas de:Establecimiento de variables por su nombre en Java

class Foo{ 
private int lorem; // 
private int ipsum;  

public setAttribute(String attr, int val){ 
    //sets attribute based on name 
} 

public static void main(String [] args){ 
    Foo f = new Foo(); 
    f.setAttribute("lorem",1); 
    f.setAttribute("ipsum",2); 
} 

public Foo(){} 
} 

..., donde se establece una variable basado en el nombre de la variable sin los nombres de las variables no modificable y sin usar ninguna otra estructura de datos. es posible?

Respuesta

24

Así es como se puede aplicar setAttribute utilizando la reflexión (he cambiado el nombre de la función, hay diferentes funciones de reflexión para los diferentes tipos de campo):

public void setIntField(String fieldName, int value) 
     throws NoSuchFieldException, IllegalAccessException { 
    Field field = getClass().getDeclaredField(fieldName); 
    field.setInt(this, value); 
} 
5

En general, desea utilizar Reflection. Aquí hay una buena introducción al topic with examples

En particular, la sección "Cambiar los valores de los campos" describe cómo hacer lo que le gustaría hacer.

Observo que el autor dice: "Esta característica es extremadamente poderosa y no tiene equivalente en otros lenguajes convencionales". Por supuesto, en los últimos diez años (el artículo fue escrito en 1998) hemos visto grandes avances en los lenguajes dinámicos. Lo anterior se realiza con bastante facilidad en Perl, Python, PHP, Ruby, etc. Sospecho que esta es la dirección de la que podría haber venido basado en la etiqueta "eval".

+0

Enlace parece estar roto; ( – Vlad

+0

He arreglado el enlace –

+0

enlace roto nuevamente – SimonPip

3

Además, eche un vistazo a BeanUtils que puede ocultar parte de la complejidad del uso de su reflejo.

0

Es posible que desee almacenar en caché algunos de los datos de reflexión mientras eres en ella:

import java.lang.reflect.Field; 
import java.util.HashMap; 

class Foo { 
    private HashMap<String, Field> fields = new HashMap<String, Field>(); 

    private void setAttribute(Field field, Object value) { 
     field.set(this, value); 
    } 

    public void setAttribute(String fieldName, Object value) { 
     if (!fields.containsKey(fieldName)) { 
      fields.put(fieldName, value); 
     } 
     setAttribute(fields.get(fieldName), value); 
    } 
} 
+0

¿Por qué molestarse cuando la capa de reflexión ya.. este caché Lee el código fuente de java.lang.Class y compruébalo por ti mismo, incluso maneja la invalidación de la memoria caché cuando una clase se vuelve a cargar. –

1

Dependiendo del uso, se puede utilizar la reflexión como estaba previsto anteriormente, o tal vez un HashMap sería más adecuado ...

1

La pregunta es específica de Ints, lo cual es útil; sin embargo, aquí hay algo un poco más general. Este tipo de método es útil si está cargando en String representaciones de pares de nombre de campo/valor de campo.

import java.lang.reflect.Field; 

public class FieldTest { 

    static boolean isValid = false; 
    static int count = 5; 

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { 
     FieldTest test = new FieldTest(); 
     test.setProperty("count", "24"); 
     System.out.println(count); 
     test.setProperty("isValid", "true"); 
     System.out.println(isValid); 
    } 

    public void setProperty(String fieldName, String value) throws NoSuchFieldException, IllegalAccessException { 
     Field field = this.getClass().getDeclaredField(fieldName); 
     if (field.getType() == Character.TYPE) {field.set(getClass(), value.charAt(0)); return;} 
     if (field.getType() == Short.TYPE) {field.set(getClass(), Short.parseShort(value)); return;} 
     if (field.getType() == Integer.TYPE) {field.set(getClass(), Integer.parseInt(value)); return;} 
     if (field.getType() == Long.TYPE) {field.set(getClass(), Long.parseLong(value)); return;} 
     if (field.getType() == Float.TYPE) {field.set(getClass(), Float.parseFloat(value)); return;} 
     if (field.getType() == Double.TYPE) {field.set(getClass(), Double.parseDouble(value)); return;} 
     if (field.getType() == Byte.TYPE) {field.set(getClass(), Byte.parseByte(value)); return;} 
     if (field.getType() == Boolean.TYPE) {field.set(getClass(), Boolean.parseBoolean(value)); return;} 
     field.set(getClass(), value); 
    } 

} 
Cuestiones relacionadas