Java Reflection для установки атрибутов - PullRequest
3 голосов
/ 15 октября 2010

У меня есть класс, который имеет много атрибутов settable / gettable. Я хотел бы использовать отражение для установки этих атрибутов, но у меня есть 2 вопроса о моей реализации

Вот некоторый урезанный код из моего класса

class Q {

  public String question_1;
  public String question_2;
  public String question_3;
  public String answer_1;
  public String answer_2;
  public String answer_3;
  //etc. etc.  Many String attributes

  // … constructor and other stuff are omitted

  // here is my method for "dynamically" setting each attribute
  public void set_attribute(String a_raw_string, String my_field) {
    try {
      Class cls = Class.forName("com.xyz.models.Q");
      Field fld = cls.getField(my_field);
      fld.set(this, a_raw_string);
  }
  catch (Throwable e) {
      System.err.println(e);
  }
}

Затем я устанавливаю следующие поля:

Q q = new Q();
q.set_attribute("abcde", "question_1");
q.set_attribute("defgh", "question_2");
// etc.

Это работает (т.е. переменные экземпляра устанавливаются, когда я вызываю set_attribute.

Однако они работают только тогда, когда переменные экземпляра объявлены как публичные. Когда они объявлены закрытыми, я получаю NoSuchFieldException

ВОПРОС 1: Почему я получаю эту ошибку, когда поля закрыты? Мое наивное предположение состоит в том, что поскольку функция set_attribute является частью класса, она должна иметь беспрепятственный доступ к переменным экземпляра.

ВОПРОС 2: Я думаю, что, возможно, переосмысливаю эту проблему (то есть, я не должен использовать отражение для установки переменных таким образом). Есть ли более рекомендуемый подход? Причина, по которой я хочу использовать рефлексию, заключается в том, что в заднице больно объявлять массу методов сеттера ... поэтому мне интересно, решил ли кто-то эту досаду лучше.

Спасибо!

Ответы [ 3 ]

1 голос
/ 15 октября 2010

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

Да.Отражение довольно медленное и должно использоваться только в качестве крайней меры.Если это просто для того, чтобы избежать избыточного кода, подумайте об использовании автоматической генерации кода.Для чистых объектов данных я настоятельно рекомендую использовать буфер протокола ;он будет генерировать геттеры / сеттеры (вам нужно только объявить поля).Кроме того, он позволяет легко обмениваться данными между C ++, Java и Python.

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

  1. Вы должны подумать, должны ли все поля быть изменяемыми.(Вам действительно нужны сеттеры?)
  2. Должны ли поля быть видимыми.(Вам вообще нужны какие-нибудь средства доступа?)

Часто хорошей идеей является сделать поля "окончательными", инициализировать их в конструкторе (ах) и не предоставлять доступ или предоставлять ограниченный доступ черезреализованный интерфейс.

0 голосов
/ 15 октября 2010
  1. Когда они являются частными, вам нужно позвонить fld.setAccessible(true);
  2. Да, почему бы вам не установить поля напрямую и избежать отражения? Не похоже, что вы делаете что-то динамичное. Просто они частные - почему? Возможно, вы хотите разоблачить методы получения и установки и сделать поля закрытыми? Если это так, то вы должны просто вызвать публичные сеттеры.
0 голосов
/ 15 октября 2010

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

Большинство IDE (например,Eclipse или NetBeans) включают инструменты для автоматического создания методов получения и установки для полей класса.

...