繁体   English   中英

Java反射设置属性

[英]Java Reflection to set attributes

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

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

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方法很麻烦……所以我想知道是否有人以更好的方式解决了这种烦恼。

谢谢!

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

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

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

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

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

使用setter方法是为类成员变量设置值的公认方法,因此绝对不应该使用反射,因为代码将更难以理解,运行起来也更加缓慢。

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

  1. 当它们是私有的时,您需要调用fld.setAccessible(true);
  2. 是的,为什么不直接设置字段并避免反射呢? 您似乎并没有动态地进行任何操作。 只是他们是私人的-为什么? 也许您的意思是公开获取者/设置者并使字段私有? 如果是这样,那么您应该只调用公共设置器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM