user494461
user494461

Reputation:

what is the preferred way of getting data from an unknown class

data is an ArrayList of Class MyType, If use just field.get(object) the code doesnt compile saying unhandled exception. When I run it, I get cannot access private members. Then I change all member fields of MyType to public. Then this code works. But surely there must be a better way of getting data?

for (Object object : data)//get one object
    {
        ArrayList<Field> fields = 
                new ArrayList<Field>(Arrays.asList(object.getClass().getDeclaredFields()));//get all its fields
        for(Field field : fields)
            {
            try {
                System.out.println(field.get(object));//print its fields value
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            }

    }

Upvotes: 2

Views: 1864

Answers (3)

Brian
Brian

Reputation: 17329

You can use setAccessible(boolean) on Field, Method, and Constructor to get access to a non-public member that the caller wouldn't normally have access to. Doing this will eliminate your error.

A more standardized approach is to use introspection. If the class follows JavaBean conventions, then you can use Introspector and BeanInfo to get PropertyDescriptor instances, which gives you access to the public read and write methods (getters and setters) of the bean. For example, here is an example bean:

public class JavaBean {

    private boolean valid;
    private String name;
    private String label;

    public boolean isValid() {
        return valid;
    }

    public String getName() {
        return name;
    }

    public String getLabel() {
        return label;
    }

    public void setValid(boolean valid) {
        this.valid = valid;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}

Here, we declare the valid, name, and label properties. Note that the field names are not used to determine the names of the properties. Instead, the get/is and set methods are used. Also notice that primitive boolean properties use is for the getter prefix.

Then to use introspection:

Object unknownType = new JavaBean();
BeanInfo javaBeanInfo = Introspector.getBeanInfo(JavaBean.class);
for (PropertyDescriptor property : javaBeanInfo.getPropertyDescriptors()) {
    System.out.println(property.getName());
}

This will print (not necessarily in order):

class
valid
name
label

class is in here because of the getClass() method present on all classes, so class is considered a property.

You can then use PropertyDescriptor.readMethod and PropertyDescriptor.writeMethod to get the Method objects that are the getter and setter respectively, then use Method.invoke on them to get and set the property value for a given object using the usual reflection APIs. PropertyDescriptor also has some other information on it, like the property type and the property name. This is an alternative to directly using reflection. It also lets others override the BeanInfo that's returned by Introspector to be a custom implementation.

Upvotes: 0

JavaDM
JavaDM

Reputation: 851

The cleanest way would be either to create an interface and to derive from this or derive from an abstract superclass. In both cases the constructs are known to the compiler. You can get a single field with reflection by the following code:

Method.class.getDeclaredField(name)

Upvotes: 1

Ajinkya
Ajinkya

Reputation: 22730

Use Field.setAccessible(true) to allow access to private fields.

try {
       field.setAccessible(true);    
       System.out.println(field.get(object));//print its fields value
     } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
                e.printStackTrace();
     }

Upvotes: 2

Related Questions