How to loop over a Class attributes in Java?

217,552

Solution 1

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.

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:

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

These are excerpts from the book:

Given a Class object, you can obtain Constructor, Method, and Field instances 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.

Solution 2

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.

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

Solution 3

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

Spring has a class named ReflectionUtils that 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:

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

Solution 4

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

Solution 5

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.

Share:
217,552

Related videos on Youtube

Zakaria
Author by

Zakaria

Binary Pixels ! Best solutions for you.

Updated on February 07, 2020

Comments

  • Zakaria
    Zakaria over 4 years

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

    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?

  • Zakaria
    Zakaria almost 14 years
    in fact, according to value of fields, I want to write or not write the value of each field?
  • polygenelubricants
    polygenelubricants almost 14 years
    @Zakaria: yes, you can accomplish this with reflection, but depending on what is it that you're trying to do, there are much better designs.
  • Zakaria
    Zakaria almost 14 years
    In fact, I have a report to generate from a class, and depending on the value of class fields I want to put or not those fields, what's the best design that can I implement.?
  • polygenelubricants
    polygenelubricants almost 14 years
    @Zakaria: Unless you want a general purpose highly customizable class report generator that works with any class, you should just stay away from reflection and just write a specific taylor-made solution for this particular class in your application domain.
  • Zakaria
    Zakaria almost 14 years
    What I want to do is to test on field value, if isn't null I want to include it in report and vice versa. I have a lot of attributes and I don't want to test them all manually so I thought that using reflection will resolve the problem. I will use it in one class. I just want to add that the result of this function is an array of String. (String[])
  • polygenelubricants
    polygenelubricants almost 14 years
    @Zakaria: go ahead and try reflection out then. There's Field.get that you can use to read the values of a field reflectively. If it's private, you may be able to get around that with setAccessible. Yes, reflection is very powerful and it lets you do things like inspecting private fields, overwriting final fields, invoking private constructors, etc. If you need further assistance with the design aspect, you should probably write a new question with a lot more information. Perhaps you don't need these many attributes in the first place (e.g. use enum or List, etc).
  • user102008
    user102008 almost 13 years
    generics has no use here. just do static void inspect(Class<?> klazz)
  • Nomad
    Nomad almost 12 years
    @polygenelubricants, thanks for such a detailed and nice answer.
  • hbprotoss
    hbprotoss over 8 years
    Is there any way to only get properties of the bean, not the class? i.e. avoid MyBean.class returned by getPropertyDescriptors
  • Jörn Horstmann
    Jörn Horstmann over 8 years
    @hbprotoss if I understand you correctly, you can check for propertyDesc.getReadMethod().getDeclaringClass() != Object.class, or you can specify a class to stop analysis as the second parameter like getBeanInfo(MyBean.class, Object.class).
  • Gewure
    Gewure over 7 years
    i like how the arguments name is "klazz" - thats very klazzy :)
  • shinzou
    shinzou over 5 years
    omitted on purpose?
  • Rickey
    Rickey over 4 years
    A class perhaps or any object.
  • QWERTY
    QWERTY over 4 years
    @Rickey Is there anyway to set a new value to the attributes by looping each fields?
  • Rickey
    Rickey over 4 years
    @hyperfkcb You may get an modification exception when attempting to change values of properties/fields you're iterating over.
  • salerokada
    salerokada about 2 years
    My problem with this solution is that getters (propertyDesc) are sorted alphabetically and I need original order of fields/getters.