Definição de variáveis ??pelo nome em Java
-
07-07-2019 - |
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?
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);
}
}