Java反射来设置属性 [英] Java Reflection to set attributes
问题描述
我有一个具有许多可设置/可获取属性的类。我想使用反射来设置这些属性,但我有两个关于我的实现的问题
这是我的一些细分代码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;
//等。许多String属性
// ...构造函数和其他东西被省略
//这里是我的动态设置每个属性的方法
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);
//等等
这是有效的(即,当我调用时设置实例变量set_attribute。
然而,它们仅在实例变量被声明为public时才起作用。当它们被声明为private时,我得到 NoSuchFieldException
问题1:为什么在字段为私有时会出现错误?我天真的假设是,由于set_attribute函数是类的一部分,它应该是可以不受限制地访问实例变量。
问题2:我想我可能会过度思考这个问题(即我不应该使用以这种方式设置变量的反射)。是否有更推荐的方法?
我想使用反射的原因是因为宣布大量的setter方法很麻烦......所以我想知道是否有人以更好的方式解决了这个烦恼。
谢谢!
我想我可能正在过度思考这个问题(即,我不应该使用反射以这种方式设置变量)
是的。反思相当缓慢,只应作为最后的手段。如果这只是为了避免拥有如此多的冗余代码,请考虑使用自动代码生成。对于纯数据对象,我强烈建议您使用协议缓冲区;它将生成getters / setter(您只需要声明字段)。此外,它还允许在C ++,Java和Python之间轻松传递数据。
如果您的类具有大量字段但不是纯数据对象...好
- 您应该考虑所有字段是否应该是可变的。 (你真的需要制定者吗?)
- 字段是否应该是可见的。 (你需要任何访问者吗?)
将字段设为最终通常是一个好主意,将它们初始化为构造函数,并且不提供访问权限或通过已实现的接口提供有限的访问权限。
I have a class that has many settable/gettable attributes. I'd like to use reflection to set these attributes, but I have 2 questions about my implementation
Here is some stripped down code from my 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);
}
}
I then set various fields like this:
Q q = new Q();
q.set_attribute("abcde", "question_1");
q.set_attribute("defgh", "question_2");
// etc.
This works (i.e., the instance variables are set when I call set_attribute.
However, they only work when the instance variables are declared public. When they are declared private I get a NoSuchFieldException
QUESTION 1: Why do I get that error when the fields are private? My naive assumption is that since the set_attribute function is part of the class, it should have unfettered access to the instance variables.
QUESTION 2: I think I may be overthinking this problem (i.e., I shouldn't be using reflection to set variables in this way). Is there a more recommended approach? The reason that I want to use reflection is because it's a pain in the ass to declare a ton of setter methods…so I'm wondering if someone has solved this annoyance in a better way.
Thanks!
I think I may be overthinking this problem (i.e., I shouldn't be using reflection to set variables in this way)
Yep. Reflection is fairly slow and should only be used as a last resort. If this is simply to avoid having so much redundant code, consider using automatic code generation. For pure data objects, I would strongly recommend using protocol buffers; it will generate the getters / setters (you only need to declare the fields). Plus it allows for easy communication of the data between C++, Java, and Python.
If you have a class that has a lot of fields but isn't a pure data object... well
- You should consider whether all the fields should be mutable. (Do you really need setters?)
- Whether the fields should even be visible. (Do you need any accessors at all?)
It is often a good idea to make fields "final", initialize them in the constructor(s), and provide no access or provide limited access through an implemented interface.
这篇关于Java反射来设置属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!