如何在Java中循环使用Class属性?

Zak*_*ria 76 java attributes loops

如何动态循环遍历java中的类属性.

例如:

public class MyClass{
    private type1 att1;
    private type2 att2;
    ...

    public void function(){
        for(var in MyClass.Attributes){
            System.out.println(var.class);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这在Java中可能吗?

pol*_*nts 91

做你所要求的没有语言支持.

您可以使用反射在运行时反射访问类型的成员(例如,Class.getDeclaredFields()使用获取数组Field),但根据您尝试执行的操作,这可能不是最佳解决方案.

也可以看看

相关问题


这是一个简单的例子,只显示反射能够做的一些事情.

import java.lang.reflect.*;

public class DumpFields {
    public static void main(String[] args) {
        inspect(String.class);
    }
    static <T> void inspect(Class<T> klazz) {
        Field[] fields = klazz.getDeclaredFields();
        System.out.printf("%d fields:%n", fields.length);
        for (Field field : fields) {
            System.out.printf("%s %s %s%n",
                Modifier.toString(field.getModifiers()),
                field.getType().getSimpleName(),
                field.getName()
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码片段使用反射来检查所有声明的字段class String; 它产生以下输出:

7 fields:
private final char[] value
private final int offset
private final int count
private int hash
private static final long serialVersionUID
private static final ObjectStreamField[] serialPersistentFields
public static final Comparator CASE_INSENSITIVE_ORDER
Run Code Online (Sandbox Code Playgroud)

Effective Java 2nd Edition,Item 53:首选接口到反射

这些是本书的摘录:

给定一个Class对象,您可以获取Constructor,MethodField表示该类的构造函数,方法和字段的实例.[他们]让你反思性地操纵他们的基础对手.然而,这种力量是有代价的:

  • 您将失去编译时检查的所有好处.
  • 执行反射访问所需的代码是笨拙和冗长的.
  • 性能受损.

通常,不应在运行时在正常应用程序中反射性地访问对象.

有一些复杂的应用程序需要反射.示例包括[...故意遗漏...]如果您对应用程序是否属于这些类别之一有任何疑问,则可能不会.


Jör*_*ann 42

直接访问字段在java中并不是很好的样式.我建议为bean的字段创建getter和setter方法,然后使用java.beans包中的Introspector和BeanInfo类.

MyBean bean = new MyBean();
BeanInfo beanInfo = Introspector.getBeanInfo(MyBean.class);
for (PropertyDescriptor propertyDesc : beanInfo.getPropertyDescriptors()) {
    String propertyName = propertyDesc.getName();
    Object value = propertyDesc.getReadMethod().invoke(bean);
}
Run Code Online (Sandbox Code Playgroud)


Sea*_*oyd 16

虽然我同意Jörn的回答,如果你的类符合JavaBeabs规范,如果它没有并且你使用Spring,这里有一个很好的选择.

Spring有一个名为ReflectionUtils的类,它提供了一些非常强大的功能,包括doWithFields(类,回调),一个访问者风格的方法,它允许你使用如下的回调对象迭代类字段:

public void analyze(Object obj){
    ReflectionUtils.doWithFields(obj.getClass(), field -> {

        System.out.println("Field name: " + field.getName());
        field.setAccessible(true);
        System.out.println("Field value: "+ field.get(obj));

    });
}
Run Code Online (Sandbox Code Playgroud)

但是这里有一个警告:该类被标记为"仅供内部使用",如果你问我,这很可惜


小智 12

迭代类字段并从对象获取值的简单方法:

 Class<?> c = obj.getClass();
 Field[] fields = c.getDeclaredFields();
 Map<String, Object> temp = new HashMap<String, Object>();

 for( Field field : fields ){
      try {
           temp.put(field.getName().toString(), field.get(obj));
      } catch (IllegalArgumentException e1) {
      } catch (IllegalAccessException e1) {
      }
 }
Run Code Online (Sandbox Code Playgroud)


Tas*_*kos 6

Java有反射(java.reflection.*),但我建议查看像Apache Beanutils这样的库,它会比直接使用反射更少毛发.