2

What is the best way to get a strongly typed value of a property, using the property name as string, of an object in Java.

For eg: A Person class with age field as an integer, say 21. If the following statement has to return integer 21 for age field, then what should be the implementation of get method? [Note: 21 is to be returned as integer]

ObjectUtils.get(person, "age");

Sample method header

public static <E> E get(Object object, String fieldName);

One way is to get the type of the field and type cast explicitly.

Other way is to use getProperty method in BeanUtils class (Apache commons library). But, the limitation is that it returns only string, but not the strongly typed value.

Is there any better approach or library utility available to achieve this?

Gopal
  • 1,372
  • 2
  • 16
  • 32
  • Java is strongly typed language! – Alpesh Gediya May 23 '13 at 10:21
  • Hi alpesh, we are not compromising type anywhere here. Using reflection, it is possible to fetch the value of a property using the property name. Just wondering whether there is any library utility or better way of achieving this? – Gopal May 23 '13 at 10:24
  • Take a look at http://stackoverflow.com/questions/6845592/get-bean-property-getter-or-setter-by-reflection – nakosspy May 23 '13 at 10:48

2 Answers2

2

The following implementation served the purpose.

@SuppressWarnings("unchecked")
public static <E> E get(Object object, String fieldName) {
    Class<?> clazz = object.getClass();
    while (clazz != null) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return (E) field.get(object);
        } catch (NoSuchFieldException e) {
            clazz = clazz.getSuperclass();
        } catch (Exception e) {
            return null;
        }
    }
    return null;
}
Gopal
  • 1,372
  • 2
  • 16
  • 32
1

Using generics as you have above will not help because you will not be able to cast to E due to type-erasure which will convert E to Object at run-time. I would suggest the following...

 public static <E> E get(Object source, String fieldName, Class<E> returnType){
      Object field = ...// get field value via reflection possibly using `ReflectionUtils`
      return returnType.cast(field);
 }

Update...

Per your comment regarding getting the Class instance from the Field via reflection. I would suggest that the above is simpler and more flexible. To make your call above you would need to do the following:

 MyType type = ObjectUtils.<MyType>get(instance, "field");

Then in the method you would need to get the Field object and from that get the Class object. In my solution the call would be

 MyType type = ObjectUtils.get(instance, "field", MyType.class);

The call is about the same just the MyType is in a different place however the code no longer need to retrieve the Class instance AND the caller can pass any class to which the field may be cast as opposed to only getting the declared type and possibly having to do a cast.

John B
  • 32,493
  • 6
  • 77
  • 98
  • Isn't the returnType redundant, as fieldName already corresponds to a property in object from which returnType can be deducted? – Gopal May 23 '13 at 10:50
  • the above is simpler and more flexible, see update for why IMO – John B May 23 '13 at 10:57