2

假设我有以下课程:

class Foo
{
   public String bar;
   public String baz;
}

我在另一个类中有以下代码:

Foo foo = new Foo();
String[] properties = {"bar", "baz"};
String[] values = {"barValue", "bazValue"};

是否可以遍历properties数组并使用它来设置 的值Foo?例如:

for (int i = 0; i < properties.length; i++)
{
  foo[ properties[i] ] = values[i];
}

像上面这样的可能吗?

4

2 回答 2

6

像上面这样的可能吗?

不。

使用您定义的属性,您唯一的选择是:

  • 编写或生成 Java 代码(或字节码)以引用字段 afoo.barfoo.baz,或

  • 使用反射。

如果您想要动态属性,请使用Map对象;例如一个HashMap<String, String>


至于您的说明性示例,那将不起作用/不起作用,因为:

  • 常规对象字段不能像数组一样被索引,并且
  • 与 C++、Python 和其他语言不同,Java 不支持任何核心语言结构(方法除外)的临时重载。

Java 不是支持这种东西的动态语言。你需要学会接受它可以为你提供的东西......或者使用不同的语言。


你是这样评论的:

反射应该对性能不利。

嗯,是的,但它是相对的。反射性地访问或更新字段可能比使用普通 Java 代码访问/更新它慢 10 到 100 倍。但是,如果您只是偶尔这样做,则性能开销可能无关紧要。如果它确实是一个问题,那么您的选择包括手写或生成代码。例如:

public class Foo
{
   public String bar;
   public String baz;

   public void setNamedProperty(String name, String value) {
       switch (name) {
       case "bar": 
           bar = value;
           break;
       case "baz": 
           baz = value;
           break;
       default:
           throw new IllegalArgumentException("Unknown property name");
       }
   }
}

就其价值而言,该代码将与在支持动态属性的语言中设置动态属性一样节省时间。(而且我怀疑它会节省空间,因为动态属性通常是使用本机编码的哈希表实现的。)

于 2013-10-13T04:35:49.157 回答
1

您可以使用Introspection,当您面对 Java Bean 时,它是一种更好的方式。

缺点是:

  • 如果它们存在,它将调用 getter/setter,或者如果没有 getter/setter 并且字段是公共的,它将直接访问字段。
  • 您可以迭代属性,因为它为您提供了一个PropertyDescriptors 数组。
  • 它支持 BeanInfo 类,
    • 所以你可以配置你的bean属性
    • 定义具有不同命名约定的访问器/修改器(不是 getter 或 setter)
  • 您可以使用类似Apache Commons BeanUtils或的库Spring BeanWrapper API

有关更多信息,请查看java.beans.Introspectorjavadocs。

顺便说一下,据我所知,Interospection 是建立在反射之上的,所以它本身就使用反射。

于 2013-10-13T05:38:43.463 回答