Java反射来设置属性 [英] Java Reflection to set attributes

查看:427
本文介绍了Java反射来设置属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是我的一些细分代码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之间轻松传递数据。



如果您的类具有大量字段但不是纯数据对象...好


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

  2. 字段是否应该是可见的。 (你需要任何访问者吗?)

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


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

  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.

这篇关于Java反射来设置属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆