Как перебирать атрибуты класса в 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 64

7 ответов:

нет языковой поддержки, чтобы сделать то, что вы просите.

вы можете рефлекторно обращаться к членам типа во время выполнения с помощью отражения (например, с 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()
            );
        }
    }
}

приведенный выше фрагмент использует отражение для проверки всех объявленных полей 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());
}