【问题标题】:Java Reflection Beans Property APIJava 反射 Bean 属性 API
【发布时间】:2011-05-02 12:03:12
【问题描述】:

是否有任何标准方法可以访问 Java Bean 属性,例如

class A {
   private String name;

   public void setName(String name){
       this.name = name;
   }

   public String getName(){
       return this.name;
   }

}

那么我可以使用反射 API 访问这个 java bean 属性名称,这样当我更改属性的值时,当我设置和获取该属性的值时会自动调用 getName 和 setName 方法

【问题讨论】:

    标签: java reflection javabeans


    【解决方案1】:

    你的问题很不清楚,但如果我明白了:

    是的。 java.beans 包有所谓的Introspector。在那里您可以读取 bean 的属性。

    BeanInfo info = Introspector.getBeanInfo(Bean.class);
    PropertyDescriptor[] pds = info.getPropertyDescriptors();
    

    您可以通过其名称找到所需的PropertyDescriptor,您可以致电getReadMethod().invoke(..)

    【讨论】:

    • 我更喜欢这种方法,因为你不需要依赖。
    • 这种方式的另一个优点是 java.lang.reflect.Method 可以重复使用,因此在同一类的不同实例上获取/写入同一属性的值可以很多更快,与使用 BeanUtils 和 20 倍 Spring BeanWrapper 相比,读取属性大约快 100 倍。由于代码示例,我也喜欢 perdi-estaquel 的答案
    【解决方案2】:

    您需要的是 BeanInfo / Introspector 机制(请参阅 Bozho 的回答)。但是,直接使用它很糟糕,因此您可以使用提供基于属性访问的库之一。最著名的大概是Apache Commons / BeanUtils(另一个是Spring的BeanWrapper抽象)

    示例代码:

    A someBean = new A();
    
    // access properties as Map
    Map<String, Object> properties = BeanUtils.describe(someBean);
    properties.set("name","Fred");
    BeanUtils.populate(someBean, properties);
    
    // access individual properties
    String oldname = BeanUtils.getProperty(someBean,"name");
    BeanUtils.setProperty(someBean,"name","Barny"); 
    

    【讨论】:

    • 只是为了无知(我),为什么不直接调用 someBean.setName("Fred")?
    • @simpatico 用于单个已知属性,显然是的。但是,如果您想管理对许多不同类型对象的许多不同属性的访问,请使用 bean 属性
    • 谢谢。如果属性设置在一个加载的文件中,我会购买它,然后只需调用 BeanUtils.populate(someBean, properties);但我从来不会在实践中调用 set("name", "Fred") 而我可以直接调用 setName("Fred") (我不是你的只是示例代码)。
    • @simpatico:如果你在编译时知道类型信息有一个setName 方法,那就是你应该使用的。否则,bean introspector 会使生活更轻松,因为它可以减少很多耦合。此外,使用自省的成本实际上并不太高(在关键的内部循环之外)。
    【解决方案3】:

    使用java.beans.PropertyDescriptor

    在你的情况下:

    A a = new A();
    PropertyDescriptor nameProperty = new PropertyDescriptor("name", A.class);
    nameProperty.getWriteMethod().invoke(a, "potato");
    System.out.println(nameProperty.getReadMethod().invoke(a));
    

    【讨论】:

      【解决方案4】:

      我已经尝试过 BeanUtils 和 PropertyDescriptors,因为我没有关于传递给我的方法的类的信息。我什至不知道传递的属性的数据类型,因此设置值变得困难。我知道 BeanUtils 应该自动为属性进行转换并设置它,但它没有为我保存数据。所以最后,我不得不依靠获得这些领域。这是我所做的:

      Field[] fields = className.getDeclaredFields();
      for (int i=0; i<fields.length ;i++)
      {
        String element = fields[i].getName();
        String propertyType = fields[i].getType().getName();
        fields[i].setAccessible(true);
        if(propertyType.equalsIgnoreCase("java.lang.Integer"))
          {
            fields[i].set(mypojoObj, Integer.parseInt(parameterValue));
          }
          else
          {
            fields[i].set(mypojoObj, parameterValue);
          }
       }
      

      我做了一个类似的 switch-case 来将所有属性类型转换为正确的类型。从页面获取时,request.getParameter(paramname) 总是返回 String,所以这种转换对我有用。任何更好的直接数据转换选项都会非常有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-16
        • 2011-09-09
        • 2012-01-30
        • 2010-09-30
        • 2010-11-21
        • 2013-10-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多