如何在java中动态读取对象属性?

Posted

技术标签:

【中文标题】如何在java中动态读取对象属性?【英文标题】:how to read object attribute dynamically in java? 【发布时间】:2011-12-06 11:10:14 【问题描述】:

有没有办法动态读取和打印对象属性(Java)?例如,如果我有以下对象

public class A
  int age ;
  String name;
  float income;



public class B
 int age;
 String name;


public class mainA
   A obj1 = new A();
   method(A);
   method(B); 


the output should be like

While running method(A):
Attribute of Object are age,name,income;
While executing method(B):
Attribute of Objects are age,name;

我的问题是我可以在 method() 中传递各种对象,有什么方法可以访问不同对象的属性。

【问题讨论】:

如果可以避免,请不要这样做,因为它会使调试变得非常痛苦。 Java 的优点之一是默认情况下它非常非魔法。如果您可以在不借助魔法或反射的情况下以某种方式做到这一点,而是使用一些非常易读和可调试的东西,从长远来看,您会做得更好。 【参考方案1】:

您想使用The Reflection API。具体看discovering class members。

您可以执行以下操作:

public void showFields(Object o) 
   Class<?> clazz = o.getClass();

   for(Field field : clazz.getDeclaredFields()) 
       //you can also use .toGenericString() instead of .getName(). This will
       //give you the type information as well.

       System.out.println(field.getName());
   

我只是想添加一个警告说明,您通常不需要做这样的事情,而对于大多数事情你可能不应该。反射会使代码难以维护和阅读。当然,在某些特定情况下您会想要使用反射,但这种情况相对较少。

【讨论】:

@Chris,感谢您的编辑,我忘记了;我知道里面一定有一个&lt;?&gt;【参考方案2】:

使用org.apache.commons.beanutils.PropertyUtils 我们可以做到这一点。如果为 bean 定义了正确的 getter 和 setter,我们还可以动态设置值:

import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;

public class PropertyDescriptorTest 

    public static void main(String[] args) 

        // Declaring and setting values on the object
        AnyObject anObject = new AnyObject();
        anObject.setIntProperty(1);
        anObject.setLongProperty(234L);
        anObject.setStrProperty("string value");

        // Getting the PropertyDescriptors for the object
        PropertyDescriptor[] objDescriptors = PropertyUtils.getPropertyDescriptors(anObject);

        // Iterating through each of the PropertyDescriptors
        for (PropertyDescriptor objDescriptor : objDescriptors) 
            try 
                String propertyName = objDescriptor.getName();
                Object propType = PropertyUtils.getPropertyType(anObject, propertyName);
                Object propValue = PropertyUtils.getProperty(anObject, propertyName);

                // Printing the details
                System.out.println("Property="+propertyName+", Type="+propType+", Value="+propValue);
             catch (Exception e) 
                e.printStackTrace();
            
        

    


设置特定属性的值:

// Here we have to make sure the value is
// of the same type as propertyName
PropertyUtils.setProperty(anObject, propertyName, value);

输出将是:

Property=class, Type=class java.lang.Class, Value=class genericTester.AnyObject
Property=intProperty, Type=int, Value=1
Property=longProperty, Type=class java.lang.Long, Value=234
Property=strProperty, Type=class java.lang.String, Value=string value

【讨论】:

org.apache.commons.beanutils.PropertyUtils 易受攻击。有更好的解决方案吗? nvd.nist.gov/vuln/detail/CVE-2019-10086【参考方案3】:

您可以使用反射从对象中获取每个字段(如果安全配置允许)。

如果您不是为了自学而需要它,那么可能值得使用来自 Apache Commons 的 ReflectionUtils。

【讨论】:

【参考方案4】:

你可以使用反射,但是 API 不是很好用。但是您尝试做的根本不是面向对象的。 A 和 B 应该有方法“打印自己”,它会输出它们的值(你应该在超类/接口中指定方法以使用多态调用方法)。

【讨论】:

感谢回复,上面的代码只是我的问题的简单版本我有同样的情况,我必须使用反射 api。【参考方案5】:

我想我会考虑另一种方法。

如果您真的想将这些数据视为数据,是否有任何理由不能将它们作为哈希表(它们是否有相关代码)?

反思会做到这一点,但这是最后的手段——在陷入反思之前,您应该始终认真考虑不同的方法。

存在必须访问此类变量的情况,例如数据库映射 (Hibernate) 和注入 (Spring)。您可能需要考虑这样的打包解决方案是否适合您的需求,以便未来的程序员无需了解您的特定解决方案的所有内容即可了解您所做的事情。

此外,Spring 注入可以满足您的需求。

此外,如果您要使用反射,请认真考虑注释,以免将您的功能与应该是简单的任意属性名称联系起来。

【讨论】:

以上是关于如何在java中动态读取对象属性?的主要内容,如果未能解决你的问题,请参考以下文章

Python如何通过字符或数字动态获取对象的名称或者属性?

如何在js中获取session中的对象的属性值

怎么给java对象添加动态添加属性和方法

如何利用java的反射机制动态创建对象

如何从数据库中读取动态属性

如何在java里面操作excel文件里面的对象