Установка переменных по имени в Java
Я хочу реализовать что-то в 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(){}
}
... где переменная задана на основе имени переменной без жестко закодированных имен переменных и без использования каких-либо других структур данных. Возможно ли это?
Ответы
Ответ 1
Здесь вы можете реализовать setAttribute
с помощью отражения (я переименовал функцию, есть разные функции отражения для разных типов полей):
public void setIntField(String fieldName, int value)
throws NoSuchFieldException, IllegalAccessException {
Field field = getClass().getDeclaredField(fieldName);
field.setInt(this, value);
}
Ответ 2
В общем, вы хотите использовать Reflection. Вот хорошее введение в тему с примерами
В частности, раздел "Изменение значений полей" описывает, как делать то, что вы хотели бы сделать.
Я отмечаю, что автор говорит: "Эта функция чрезвычайно эффективна и не имеет эквивалента на других традиционных языках". Конечно, за последние десять лет (статья была написана в 1998 году) мы добились больших успехов на динамических языках. Вышеизложенное довольно легко выполняется в Perl, Python, PHP, Ruby и т.д. Я подозреваю, что это направление, из которого вы, возможно, пришли, основываясь на теге eval.
Ответ 3
Кроме того, посмотрите BeanUtils, который может скрыть некоторые сложности использования отражения от вас.
Ответ 4
В зависимости от использования вы можете использовать отражение, как указано выше, или, возможно, HashMap будет лучше подходит...
Ответ 5
Вопрос специфичен для ints, что полезно, однако вот что-то более общее. Этот тип метода полезен, если вы загружаете в String
представления пар значений полей/полей поля.
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);
}
}
Ответ 6
Возможно, вам захочется кэшировать некоторые данные отражения, пока вы на нем:
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);
}
}