Как перебирать атрибуты класса в Java?
Как я могу циклически перебирать атрибуты класса в java динамически.
например :
public class MyClass
{
private type1 att1;
private type2 att2;
...
public void function()
{
for(var in MyClass.Attributes)
{
System.out.println(var.class);
}
}
}
возможно ли это в Java?
7 ответов:
нет языковой поддержки, чтобы сделать то, что вы просите.
вы можете рефлекторно обращаться к членам типа во время выполнения с помощью отражения (например, с
Class.getDeclaredFields()
чтобы получить массивField
), но в зависимости от того, что вы пытаетесь сделать, это может не быть лучшим решением.см. также
вопросы
- что такое рефлексия, и почему она полезна?
- Java отражение: почему это так плохо?
- как отражение не может привести к запахам кода?
- сброс свойств объекта java
пример
вот простой пример, чтобы показать только часть того, что рефлексия способна на это.
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() ); } } }
приведенный выше фрагмент использует отражение для проверки всех объявленных полей
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 2-е издание, пункт 53: предпочитайте интерфейсы отражению
вот выдержки из книги:
дали
Class
доступ к полям напрямую не очень хороший стиль в java. Я бы предложил создать методы getter и setter для полей вашего компонента, а затем использовать классы Introspector и BeanInfo из java.фасоль пакет.
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); }
хотя я согласен с ответ Йорна Если ваш класс соответствует спецификации 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)); }); }
но вот предупреждение: класс помечен как "только для внутреннего использования", что очень жаль, если вы спросите меня
простой способ перебора полей класса и получения значений из объекта:
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 имеет отражение (java.отображение.* ), но я бы предложил заглянуть в библиотеку, такую как Apache Beanutils, это сделает процесс гораздо менее волосатым, чем использование отражения напрямую.
вы можете зацикливать атрибуты класса динамически с помощью java Reflections API -
for (Field field : objClass.getDeclaredFields()) { // Invoke the getter method on the Institution1 object. Object objField = new PropertyDescriptor(field.getName(), Institute1.class).getReadMethod().invoke(inst1);
вот решение, которое сортирует свойства в алфавитном порядке и печатает их все вместе с их значениями:
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()); }