Устанавливание значения в объект с помощью отражения

У меня есть объект, который имеет много атрибутов, каждый с он - метод считывания и метод set. Каждый атрибут имеет не тип примитива, который я не знаю во времени выполнения.

Например, то, что я имею, является этим:

public class a{

    private typeA attr1;
    private typeB attr2;

    public typeA getAttr1(){ return attr1; }
    public typeB getAttr2(){ return attr2; }

    public void setAttr1(typeA at){ attr1 = at; }
    public void setAttr2(typeB at){ attr2 = at; }
}

public class typeA{
    public typeA(){
        // doesn't matter
    }
}

public class typeB{
    public typeB(){
        // doesn't matter
    }
}

Так, с помощью отражения я получил метод установщика для атрибута. Устанавливание значения стандартным способом является чем-то вроде этого:

a test = new a();
a.setAttr1(new typeA());

Но как я могу сделать это отражение использования? Я уже получил setAttr1 () метод с помощью отражения, но я не знаю, как создать новый объект typeA, который будет вставлен в метод set.

5
задан marionmaiden 28 April 2010 в 19:48
поделиться

4 ответа

Используйте Class # newInstance () .

Class<TypeA> cls = TypeA.class;
TypeA typeA = cls.newInstance();

Или, в вашем конкретном случае, когда вам нужно определить тип параметра метода:

Class<?> cls = setterMethod.getParameterTypes()[0];
Object value = cls.newInstance();
setterMethod.invoke(bean, value);

Вы можете узнать больше об отражении в учебнике Sun по этому вопросу . При этом имена классов должны начинаться с верхнего регистра. Я исправил это в приведенном выше примере.

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

11
ответ дан 18 December 2019 в 09:48
поделиться

Используйте метод getDeclaredFields () в объекте Class , чтобы получить все поля, затем используйте field.set (classInstance, value) , чтобы установить значение поля в экземпляре. Примечание: вам может потребоваться установить для поля доступный флаг значение true, если поле является частным. Не нужно полагаться на методы установки.

3
ответ дан 18 December 2019 в 09:48
поделиться

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

Проблема: - Мне нужно большое количество полей для хранения этих данных - Все эти поля требуют огромного количества шаблонов

Решение:

  • используйте отражение, чтобы уменьшить шаблон <"вы здесь"
  • Используйте метаданные, чтобы указать, как следует использовать поля

Новые проблемы:

  • Отражение трудно понять, когда кто-то новый смотрит на код
  • Как только вы go meta достаточно, чтобы исключить больше шаблонов, поля часто не упоминаются в коде, кроме как в метаданных - почему они поля?
  • Указание метаданных в коде довольно быстро становится громоздким (самый простой способ - это строковый массив, способ)

Решение: Начните хранить данные в коллекции и укажите метаданные во внешнем файле данных

Новая проблема: Ошибки становится трудно найти

Тщательно проверяйте ошибки и очень четко указывайте свои сообщения об ошибках. Убедитесь, что другие программисты, которые могут использовать ваш код, прочитали сообщения об ошибках. Попытка указать, когда метаданные отсутствуют или неверны, и как программист должен обновлять метданные - включая расположение файла метаданных.

Проблема: Нет безопасности типов

Да, временами это немного раздражало. В итоге я включил информацию о типе в метаданные, чтобы, если кто-то поместил неправильное значение в поле, его можно было обнаружить - по сути, это перемещает безопасность типов со времени сборки на время выполнения, что в моем случае было нормально.

Проблема: метаданные необходимы неоднократно на протяжении всего жизненного цикла объекта.

Вместо того, чтобы искать их по имени каждый раз, когда они используются, я бы проанализировал метаданные в начале и поместил их в объект (назовем это IntHolder). Этот держатель окажется в хеш-таблице и будет содержать текущее значение, а также ссылку на проанализированные метаданные.

Пример

Вот какие будут мои метаданные для одного поля таблицы стилей:

FieldName:     Age
FieldType      Integer
ScreenBinding: AgeTextField
DBBinding:     User.age
Validation:    IntRange(0, 120); "Age is out of range"

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

Когда вам все же нужно использовать, используйте getInt ("Age") и setInt ("Age", 12) вместо getAge () и setAge (12) - немного более подробно, но это не проблема.

Если это проблема, вы можете создать вспомогательные методы getAge / setAge, и вам никогда не нужно знать, что это не поле, но это снова начинает накапливаться в шаблоне.

FieldType: определяет способ хранения и позволяет реализовать проверку типов.

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

Самое интересное - это проверка. При извлечении данных с экрана они могут быть переданы валидатору очень программным способом. Тот же валидатор можно использовать перед фиксацией в БД.

Валидаторы могут намного больше, они могут действовать как триггеры (если значение изменяется, сделайте это) или действия (когда пользователь отправляет экран, сделайте это).Это простые объекты с возможностью принимать значение (через интерфейс) - они могут быть такими гибкими или мощными, как вам нравится, но не привязаны напрямую к какому-либо объекту, кроме как через метаданные.

Единственная проблема с этим подходом заключается в том, что вы должны быть программистом, который любит писать фикстуры, а не подверженный ошибкам шаблон. (Да, я считаю, что количество времени примерно одинаковое, но я обычно очень медленно работаю, когда мне нужно реализовать шаблон)

После того, как я проделал это несколько раз, мне действительно понравился шаблон, но его трудно реализовать. В следующий раз, когда я это сделаю, я попытаюсь превратить его в какую-нибудь библиотеку.

2
ответ дан 18 December 2019 в 09:48
поделиться

Если вы хотите установить "свежий" объект в каждом сеттере вашего класса, вы обычно можете сделать это, получив Method, для каждого метода вы получаете Class аргументов с getParameterTypes() , для каждого вызываемого класса Class.newInstance() ... и скрестите пальцы (что должно порвать с примитивными типами - я сомневаюсь, что Java делает автобоксинг здесь). Вы всегда можете спросить, является ли параметр пимитивным вызовом isPrimitive()

Зачем вам устанавливать "пустые" экземпляры для примитивных полей класса?Они уже инициализированы. Хотите их «сбросить»?

1
ответ дан 18 December 2019 в 09:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: