Использование отражения для установки свойства объекта

Я получаю класс по имени, и мне нужно обновить их соответствующими данными, и мой вопрос в том, как это сделать с помощью java. Я хочу добавить в метод некоторые фиктивные данные. Я не знаю тип класса, я просто получаю имя класса и использую отражение, чтобы получить его данные.

Я использую этот код, чтобы получить экземпляр класса и

Class<?> classHandle = Class.forName(className);

Object myObject = classHandle.newInstance();

// iterate through all the methods declared by the class
for (Method method : classHandle.getMethods()) {
    // find all the set methods
    if (method.getName().matches("set[A-Z].*")

И знайте, что я нахожу список заданного метода, я хочу обновить его данными, как я могу это сделать.

предположим, что в имени класса у меня есть человек, а в классе есть setSalary и setFirstName и т. д., как я могу установить их с отражением?

public class Person {

    public void setSalery(double salery) {
        this.salery = salery;
    }

    public void setFirstName(String FirstName) {
        this.FirstName = FirstName;
    }   
}

person Stefan Strooves    schedule 17.01.2013    source источник


Ответы (3)


Вместо того, чтобы пытаться вызвать сеттер, вы также можете просто напрямую установить значение свойства, используя отражение. Например:

public static boolean set(Object object, String fieldName, Object fieldValue) {
    Class<?> clazz = object.getClass();
    while (clazz != null) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(object, fieldValue);
            return true;
        } catch (NoSuchFieldException e) {
            clazz = clazz.getSuperclass();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
    return false;
}

Вызов:

Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
set(instance, "salary", 15);
set(instance, "firstname", "John");

К вашему сведению, вот эквивалентный общий геттер:

@SuppressWarnings("unchecked")
public static <V> V get(Object object, String fieldName) {
    Class<?> clazz = object.getClass();
    while (clazz != null) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return (V) field.get(object);
        } catch (NoSuchFieldException e) {
            clazz = clazz.getSuperclass();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
    return null;
}

Вызов:

Class<?> clazz = Class.forName(className);
Object instance = clazz.newInstance();
int salary = get(instance, "salary");
String firstname = get(instance, "firstname");
person sp00m    schedule 17.01.2013
comment
Спасибо за ваш повтор, проблема в том, что я не знаю зарплату и имя, так как каждый раз, когда я могу получить другой класс, поэтому я могу использовать что-то вроде set(myObject, salery, 15); - person Stefan Strooves; 17.01.2013
comment
@StefanStrooves Итак, как вы узнаете, какое поле вы должны установить для какого класса? - person sp00m; 17.01.2013
comment
одно важное предположение состоит в том, что все классы, которые я могу получить, имеют соответствующий набор и получают для каждого члена, нет возможности установить какое-то поле без получения или наоборот - person Stefan Strooves; 17.01.2013
comment
что, если модификаторы являются частными? Этот метод, безусловно, нельзя использовать для независимой установки свойств. - person Akah; 07.05.2016
comment
@larrytech Reflection более мощный, чем вы думаете: stackoverflow.com/a/3301720/1225328;) - person sp00m; 01.10.2016
comment
зачем зацикливаться на этом?? в то время как (clazz != ноль) ? - person Vikash; 27.03.2018
comment
@Vikash class перезаписывается в блоке catch NoSuchFieldException. Этот цикл в основном перемещается вверх по иерархии классов, поэтому, если данный fieldName не найден в классе экземпляра, будут проверены родительские классы. - person sp00m; 27.03.2018
comment
Спасибо @sp00m. Это действительно полезно. Не могли бы вы поделиться способом установки ArrayList и HashMap с помощью отражения? - person learner; 13.07.2018

if (method.getName().matches("set[A-Z].*") {
  method.invoke(person,salary)
  // and so on
}

чтобы узнать параметры, вы можете выдать method.getPagetParameterTypes() на основе результата построения ваших параметров и питания.

person TheWhiteRabbit    schedule 17.01.2013
comment
Вопрос (я думаю) в том, как определить аргументы для отправки - как определить, ожидает ли текущий объект method double или String, и после определения этого - как узнать, что отправить методу. - person amit; 17.01.2013
comment
Странное предположение, поскольку в вопросе ничего подобного не упоминается. - person Kurt Du Bois; 17.01.2013

Чтобы обновить имя

  • Сначала найдите поле, которое вы хотите обновить
  • Затем найдите мутатор (который принимает аргумент типа поля)
  • Наконец, выполните мутатор для объекта с новым значением:
Field field=classHandle.getDeclaredField("firstName");
Method setter=classHandle.getMethod("setFirstName", field.getType());
setter.invoke(myObject, "new value for first name");
person paralaks    schedule 12.07.2016