Question

Je cherche à implémenter quelque chose en Java dans le sens suivant:

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(){}
}

... où une variable est définie en fonction du nom de la variable sans les noms de variable codés en dur et sans utiliser d'autres structures de données. Est-ce possible?

Était-ce utile?

La solution

Voici comment implémenter setAttribute en utilisant la réflexion (j'ai renommé la fonction; il existe différentes fonctions de réflexion pour différents types de champs):

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

Autres conseils

En général, vous souhaitez utiliser la réflexion. Voici une bonne introduction au rubrique avec exemples

En particulier, le " Changer les valeurs des champs " Cette section explique comment faire ce que vous souhaitez faire.

Je remarque que l'auteur a déclaré: "Cette fonctionnalité est extrêmement puissante et n'a pas d'équivalent dans les autres langues conventionnelles." Bien sûr, au cours des dix dernières années (l'article a été écrit en 1998), nous avons assisté à de grands progrès dans les langages dynamiques. Ce qui précède se fait assez facilement en Perl, Python, PHP, Ruby, etc. Je soupçonne que c’est la direction dans laquelle vous vous êtes peut-être inspiré de l'option "eval" tag.

Consultez également BeanUtils pour masquer une partie de la complexité liée à l'utilisation de la réflexion vous.

La question est spécifique à ints, ce qui est utile, mais voici quelque chose d'un peu plus général. Ce type de méthode est utile si vous chargez des représentations String de paires nom / valeur de champ.

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);
    }

}

En fonction de l'utilisation, vous pouvez utiliser la réflexion comme indiqué ci-dessus, ou peut-être qu'un HashMap conviendrait mieux ...

Vous voudrez peut-être mettre en cache certaines des données de réflexion pendant que vous y êtes:

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);
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top