Pergunta

Eu estou olhando para implementar algo em Java ao longo das linhas de:

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

... onde uma variável é definida com base no nome variável sem os nomes das variáveis ??codificadas e sem o uso de quaisquer outras estruturas de dados. Isso é possível?

Foi útil?

Solução

Veja como você pode implementar setAttribute usando a reflexão (que eu renomeado a função; existem diferentes funções reflexão para diferentes tipos de campo):

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

Outras dicas

Em geral, você quer usar a reflexão. Aqui está uma boa introdução para o tema com exemplos

Em particular, a seção "Alterando Valores de Campos" descreve como fazer o que você gostaria de fazer.

Faço notar que o autor diz: "Este recurso é extremamente poderoso e não tem equivalente em outros idiomas convencionais." É claro que, nos últimos anos dez (o artigo foi escrito em 1998) temos visto grandes avanços feitos em linguagens dinâmicas. A descrição acima é facilmente feito em Perl, Python, PHP, Ruby, e assim por diante. Eu suspeito que esta é a direção que você pode ter vindo da base na tag "eval".

Além disso, dê uma olhada BeanUtils que pode esconder um pouco da complexidade do uso de reflexão a partir você.

A questão é específico para ints, que é útil, no entanto aqui é algo um pouco mais geral. Este tipo de método é útil se você estiver carregando nas representações String de nome de campo / valor pares 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);
    }

}

Dependendo do uso, você pode usar a reflexão como recomendado acima, ou talvez um HashMap seria mais adequado ...

Você pode querer armazenar em cache alguns dos dados reflexão enquanto você está nisso:

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);
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top