Reputation:
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
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
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
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