如何遍历Java中的类属性?
我怎样才能dynamic地在java中循环一个类的属性。
例如:
public class MyClass { private type1 att1; private type2 att2; ... public void function() { for(var in MyClass.Attributes) { System.out.println(var.class); } } }
这在Java中可能吗?
没有语言支持去做你所要求的。
你可以在运行时使用reflection(例如用Class.getDeclaredFields()
获得一个Field
数组Class.getDeclaredFields()
来reflection地访问一个types的成员,但根据你想要做什么,这可能不是最好的解决scheme。
也可以看看
- Java教程:reflectionAPI / 高级语言主题:反思
相关问题
- 什么是反思,为什么它有用?
- Java反思:为什么这么糟糕?
- Reflection如何不会导致代码味道?
- 转储一个Java对象的属性
例
下面是一个简单的例子,只显示一些reflection能够做的事情。
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() ); } } }
上面的代码片段使用reflection来检查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
有效的Java第二版,项目53:喜欢接口reflection
这些是这本书的摘录:
给定一个
Class
对象,您可以获得表示该类的构造函数,方法和字段的Constructor
,Method
和Field
实例。 [他们]让你反思性地操纵他们的底层。 然而,这种力量的代价是:
- 你失去了编译时检查的所有好处。
- 执行reflection访问所需的代码笨拙而冗长。
- 性能受损。
通常,在运行时,不应该在正常应用程序中reflection访问对象。
有一些复杂的应用程序需要反思。 例子包括[……故意省略]如果您对您的应用程序是否属于这些类别有任何疑问,则可能不会。
在java中直接访问字段并不是很好的风格。 我build议为你的bean的字段创buildgetter和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); }
虽然我同意Jörn的回答 ,但是如果你使用spring的话,还是有更优雅的可能性。
Spring有一个名为ReflectionUtils的类,它提供了一些非常强大的function,包括doWithFields(class,callback) ,这是一种访问者风格的方法,可以让你用类似下面的callback对象迭代类字段:
public void analyze(Object obj){ ReflectionUtils.doWithFields(obj.getClass(), new FieldCallback(){ @Override public void doWith(final Field field) throws IllegalArgumentException, IllegalAccessException { System.out.println("Field name: " + field.getName()); field.setAccessible(true); System.out.println("Field value: "+ field.get(obj)); } }); }
但是,这里有一个警告:class级被贴上“只供内部使用”,如果你问我,这真是可惜
迭代类字段并从对象获取值的简单方法:
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) { } }
Java有Reflection(java.reflection。*),但是我build议寻找像Apache Beanutils这样的库,它会使得这个过程比直接使用reflection要less得多。
您可以使用Java Reflections APIdynamic地循环类属性,
for (Field field : objClass.getDeclaredFields()) { // Invoke the getter method on the Institution1 object. Object objField = new PropertyDescriptor(field.getName(), Institute1.class).getReadMethod().invoke(inst1);
这是一个解决scheme,按字母顺序排列属性,并将它们与它们的值一起打印出来:
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()); }