Java反射设置属性

发布于 2024-09-27 09:33:58 字数 1252 浏览 8 评论 0原文

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

这是我的类中的一些精简代码,

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 方法是一件很痛苦的事情……所以我想知道是否有人以更好的方式解决了这个烦恼。

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

少年亿悲伤 2024-10-04 09:33:58

我认为我可能过度思考这个问题(即,我不应该使用反射以这种方式设置变量)

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

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

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

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

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

  1. You should consider whether all the fields should be mutable. (Do you really need setters?)
  2. 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.

感性不性感 2024-10-04 09:33:58

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

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

Using setter methods is the accepted way to set values for class member variables, reflection should definitely not be used for that as the code will be harder to understand and run much more slowly.

Most IDEs (eg Eclipse or NetBeans) include tools for automatically creating getter and setter methods for a class's fields.

安人多梦 2024-10-04 09:33:58
  1. 当它们是私有的时,您需要调用 fld.setAccessible(true);
  2. 是的,为什么不直接设置字段并避免反射呢?看起来你没有做任何动态的事情。只是它们是私人的——为什么呢?也许您的意思是公开 getter/setter 并将字段设为私有?如果是这样,那么您应该只调用公共设置器。
  1. When they are private you need to call fld.setAccessible(true);
  2. Yes, why don't you just set the fields directly and avoid reflection? It doesn't look like you're doing anything dynamic. It's just that they are private -- why? Perhaps you mean to expose getters/setters and make the fields private? If so, then you should just invoke the public setters.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文