Javareflection来设置属性

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

这是我class上的一些精简代码

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:我想我可能正在过度思考这个问题(即,我不应该使用reflection以这种方式设置变量)。 有更推荐的方法吗? 我想要使​​用reflection的原因是因为宣布大量的二次方法是很痛苦的…所以我想知道是否有人以更好的方式解决了这个烦恼。

谢谢!

我想我可能会过度思考这个问题(也就是说,我不应该使用reflection以这种方式设置变量)

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

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

  1. 您应该考虑所有字段是否应该是可变的。 (你真的需要制定者吗?)
  2. 字段是否应该是可见的。 (你需要任何访问者吗?)

通常一个好主意是使字段“最终”,在构造函数中初始化它们,并且不提供访问权限或通过实现的接口提供有限的访问权限。

使用setter方法是为类成员变量设置值的可接受方法,绝对不应该使用reflection,因为代码将更难理解并且运行速度更慢。

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

  1. 当它们是私有的时,你需要调用fld.setAccessible(true);
  2. 是的,为什么不直接设置字段并避免reflection? 它看起来并不像你在做任何动态的事情。 只是他们是私人的 – 为什么? 也许你的意思是暴露getter / setter并将字段设为私有? 如果是这样,那么你应该只调用公共setter。