小编典典

Java Reflection设置属性

java

我有一个具有许多可设置/可获取的属性的类。我想使用 反射 来设置这些属性,但是我对实现有两个问题

这是我班上的一些简化代码

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时设置实例变量。

但是,它们仅在实例变量被声明为public时起作用。当它们被声明为私有时,我得到一个 NoSuchFieldException

问题1: 当字段为私有时,为什么会出现该错误?我的天真假设是,由于set_attribute函数是类的一部分,因此它应该可以不受限制地访问实例变量。

问题2:
我认为我可能对这个问题有过多的想法(即,我不应该使用反射来设置变量)。是否有更推荐的方法?我之所以要使用反射,是因为要声明大量的setter方法非常麻烦……所以我想知道是否有人以更好的方式解决了这种烦恼。

谢谢!


阅读 214

收藏
2020-11-01

共1个答案

小编典典

我想我可能对此想法太想了(即,我不应该以这种方式使用反射来设置变量)

是的
反射是相当缓慢的,仅应作为最后的手段。如果只是为了避免有太多冗余代码,请考虑使用自动代码生成。对于纯数据对象,我强烈建议您使用协议缓冲区;它将生成getters
/ setters(您只需要声明字段)。另外,它还允许在C ++,Java和Python之间轻松进行数据通信。

如果您有一个具有很多字段但又不是纯数据对象的类…那么

  1. 您应该考虑所有字段是否应该都是可变的。(您真的需要二传手吗?)
  2. 字段是否应该可见。(您是否需要任何访问器?)

通常,将字段设为“最终”,在构造函数中对其进行初始化,并且不提供任何访问权限或通过已实现的接口提供有限的访问权限,通常是一个好主意。

2020-11-01