Java反射设置属性

3

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

以下是我类中剥离出来的一些代码:

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:我认为可能过度思考了这个问题(即我不应该使用反射以这种方式设置变量)。是否有更推荐的方法?我想使用反射的原因是声明大量setter方法很麻烦...所以我想知道是否有人已经找到了更好的解决办法。

谢谢!


当您拥有标签/值对的映射并且想要加载一个POJO时,这就是有趣的事情。 - Tony Ennis
你能解释一下为什么你想使用反射,或者说为什么你不想使用常规的设置方法吗?我问这个问题是因为我不太明白你真正的问题是什么。 - pgras
3个回答

1
我觉得我可能在过度思考这个问题(即,我不应该使用反射来设置变量)
是的。反射相当慢,应该只作为最后的手段使用。如果这只是为了避免有太多冗余代码,考虑使用自动代码生成。对于纯数据对象,我强烈建议使用协议缓冲区;它将生成getter/setter(您只需要声明字段)。此外,它允许在C++、Java和Python之间轻松传递数据。
如果您有一个具有许多字段但不是纯数据对象的类...好吧
1. 您应该考虑是否所有字段都应该是可变的。(您真的需要setter吗?) 2. 字段是否应该可见。(您需要任何访问器吗?)
通常最好将字段设为“final”,在构造函数中初始化它们,并提供无访问或通过实现接口提供有限访问。

0

使用setter方法是设置类成员变量值的公认方式,反射绝对不应该用于此,因为代码会更难理解,并且运行速度会变慢。

大多数IDE(例如Eclipse或NetBeans)都包括自动创建getter和setter方法的工具,用于类字段。


0
  1. 当它们是私有的时候,你需要调用 fld.setAccessible(true);
  2. 是的,为什么不直接设置字段而避免使用反射呢?看起来你并没有做任何动态的事情。只是它们是私有的——为什么?也许你想公开getter/setter并将字段设为私有的?如果是这样,那么你应该直接调用公共的setter。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接