简体   繁体   English

Java反射设置属性

[英]Java Reflection to set attributes

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 (ie, the instance variables are set when I call set_attribute. 这有效(即,当我调用set_attribute时设置实例变量。

However, they only work when the instance variables are declared public. 但是,它们仅在实例变量被声明为public时起作用。 When they are declared private I get a NoSuchFieldException 当它们被声明为私有时,我得到一个NoSuchFieldException

QUESTION 1: Why do I get that error when the fields are private? 问题1:当字段为私有时,为什么会出现该错误? My naive assumption is that since the set_attribute function is part of the class, it should have unfettered access to the instance variables. 我的天真的假设是,由于set_attribute函数是类的一部分,因此它应该可以不受限制地访问实例变量。

QUESTION 2: I think I may be overthinking this problem (ie, I shouldn't be using reflection to set variables in this way). 问题2:我认为我可能对此问题思考过多(即,我不应该使用反射来设置变量)。 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. 我之所以要使用反射,是因为要声明大量的setter方法很麻烦……所以我想知道是否有人以更好的方式解决了这种烦恼。

Thanks! 谢谢!

I think I may be overthinking this problem (ie, 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). 它将生成getters / setters(您只需要声明字段)。 Plus it allows for easy communication of the data between C++, Java, and Python. 另外,它还允许在C ++,Java和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. 通常,将字段设置为“最终”,在构造函数中对其进行初始化,并且不提供任何访问或通过已实现的接口提供有限的访问,通常是一个好主意。

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

Most IDEs (eg Eclipse or NetBeans) include tools for automatically creating getter and setter methods for a class's fields. 大多数IDE(例如Eclipse或NetBeans)都包含用于自动为类的字段创建getter和setter方法的工具。

  1. When they are private you need to call fld.setAccessible(true); 当它们是私有的时,您需要调用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. 如果是这样,那么您应该只调用公共设置器。

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

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