如何循环 Java 中的类属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3333974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 22:19:48  来源:igfitidea点击:

How to loop over a Class attributes in Java?

javaattributesloops

提问by Zakaria

How can I loop over a class attributes in java dynamically.

如何动态循环 java 中的类属性。

For eg :

例如:

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

    public void function(){
        for(var in MyClass.Attributes){
            System.out.println(var.class);
        }
    }
}

is this possible in Java?

这在Java中可能吗?

采纳答案by polygenelubricants

There is no linguistic support to do what you're asking for.

没有语言支持来执行您的要求。

You can reflectively access the members of a type at run-time using reflection (e.g. with Class.getDeclaredFields()to get an array of Field), but depending on what you're trying to do, this may not be the best solution.

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

See also

也可以看看

Related questions

相关问题



Example

例子

Here's a simple example to show only some of what reflection is capable of doing.

下面是一个简单的例子,只展示了反射能够做的一些事情。

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()
            );
        }
    }
}

The above snippet uses reflection to inspect all the declared fields of class String; it produces the following output:

上面的代码片段使用反射来检查所有声明的字段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


Effective Java 2nd Edition, Item 53: Prefer interfaces to reflection

Effective Java 2nd Edition,第 53 条:比反射更喜欢接口

These are excerpts from the book:

这些是书中的摘录:

Given a Classobject, you can obtain Constructor, Method, and Fieldinstances representing the constructors, methods and fields of the class. [They] let you manipulate their underlying counterparts reflectively. This power, however, comes at a price:

  • You lose all the benefits of compile-time checking.
  • The code required to perform reflective access is clumsy and verbose.
  • Performance suffers.

As a rule, objects should not be accessed reflectively in normal applications at runtime.

There are a few sophisticated applications that require reflection. Examples include [...omitted on purpose...]If you have any doubts as to whether your application falls into one of these categories, it probably doesn't.

给定一个Class对象,你可以获取ConstructorMethod以及Field代表类的构造函数,方法和字段的实例。[他们] 让你反思性地操纵他们的底层对手。然而,这种力量是有代价的:

  • 您将失去编译时检查的所有好处。
  • 执行反射访问所需的代码笨拙而冗长。
  • 性能受到影响。

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

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

回答by Tassos Bassoukos

Java has Reflection (java.reflection.*), but I would suggest looking into a library like Apache Beanutils, it will make the process much less hairy than using reflection directly.

Java 有反射 (java.reflection.*),但我建议查看像 Apache Beanutils 这样的库,它会使这个过程比直接使用反射少很多麻烦。

回答by J?rn Horstmann

Accessing the fields directly is not really good style in java. I would suggest creating getter and setter methods for the fields of your bean and then using then Introspector and BeanInfo classes from the java.beans package.

在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);
}

回答by Sean Patrick Floyd

While I agree with J?rn's answerif your class conforms to the JavaBeabs spec, here is a good alternative if it doesn't and you use Spring.

如果您的类符合 JavaBeabs 规范,我同意J?rn 的回答,但如果不符合并且您使用 Spring,这里是一个不错的选择。

Spring has a class named ReflectionUtilsthat offers some very powerful functionality, including doWithFields(class, callback), a visitor-style method that lets you iterate over a classes fields using a callback object like this:

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

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));

    });
}

But here's a warning: the class is labeled as "for internal use only", which is a pity if you ask me

但是这里有一个警告:该类被标记为“仅供内部使用”,如果您问我,这很遗憾

回答by Rickey

Simple way to iterate over class fields and obtain values from object:

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

 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) {
      }
 }

回答by Benny Neugebauer

Here is a solution which sorts the properties alphabetically and prints them all together with their values:

这是一个按字母顺序对属性进行排序并将它们连同它们的值一起打印的解决方案:

public void logProperties() throws IllegalArgumentException, IllegalAccessException {
  Class<?> aClass = this.getClass();
  Field[] declaredFields = aClass.getDeclaredFields();
  Map<String, String> logEntries = new HashMap<>();

  for (Field field : declaredFields) {
    field.setAccessible(true);

    Object[] arguments = new Object[]{
      field.getName(),
      field.getType().getSimpleName(),
      String.valueOf(field.get(this))
    };

    String template = "- Property: {0} (Type: {1}, Value: {2})";
    String logMessage = System.getProperty("line.separator")
            + MessageFormat.format(template, arguments);

    logEntries.put(field.getName(), logMessage);
  }

  SortedSet<String> sortedLog = new TreeSet<>(logEntries.keySet());

  StringBuilder sb = new StringBuilder("Class properties:");

  Iterator<String> it = sortedLog.iterator();
  while (it.hasNext()) {
    String key = it.next();
    sb.append(logEntries.get(key));
  }

  System.out.println(sb.toString());
}