Sunday, January 4, 2009

Using Reflection to implement toString() for beans

I borrowed some reflection code to implement toString() methods for some bean objects. However this resulted in this code being strewn around all over the place. The code which I took was accessing the private fields of the objects, hence couldn't be used either in a superclass or couldn't be extracted as a method in a util class. I then thought it might be  a better idea to access the public methods instead, and now I have all the code in one class. All you need to do is put a call to the method getStringForBean() in your bean's toString() method. Or if you have a class hierarchy, with one base class being the parent for all other bean classes (as it was in my case), then you can put in the base class. I am also putting the old method or code  in getStringForObject() method. If your class doesn not have public accessor methods you can paste this code into the individual classes. 

Please let me know if you have any comments or suggestions  


public class ReflectionUtils {
      private static final String GET = "get";
      private static final String IS = "is";

      /**
       *
       * @param obj - A bean with accessor methods starting with get or is
       * @return
       */
      public static String getStringForBean(Object obj) {
            StringBuilder result = new StringBuilder();
            String newLine = System.getProperty("line.separator");
            result.append(obj.getClass().getName());
            result.append(" Object {");
            result.append(newLine);
            // determine fields declared in this class only (no fields of
            // superclass)
            Method[] methods = obj.getClass().getMethods();
            for(Method method : methods) {
                  result.append("  ");
                  String methodName = method.getName();
                  String methodPrefix = "";

                  boolean accessorMethod = false;

                  if (methodName.startsWith(GET)) {

                        methodPrefix = GET;

                        accessorMethod = true;

                  }

                  if (methodName.startsWith(IS)) {
                        methodPrefix = IS;
                        accessorMethod = true;
                  }

                  if (accessorMethod == true) {
                        try {
                              String fieldName = methodName.substring(methodPrefix

                                          .length(), methodName.length());

                              fieldName = Character.toLowerCase(fieldName.charAt(0))

                                          + fieldName.substring(1);

                              Object value = (Object) method.invoke(obj, (Object[]) null);

                              result.append(fieldName);

                              result.append(": ");

                              // requires access to private field:

                              result.append(value);

                              result.append("  ");

                        } catch (IllegalArgumentException e) {

                              e.printStackTrace();

                        } catch (IllegalAccessException e) {

                              e.printStackTrace();

                        } catch (InvocationTargetException e) {

                              e.printStackTrace();

                        }

                  }

            }

            if(result.length() > 0 && result.charAt(result.length() - 1) == ',') {

                  result.deleteCharAt(result.length() - 1);

            }
            result.append(newLine);
            result.append("}");
            return result.toString();

      }

      private static String getStringForObject(Object obj) {

            StringBuilder result = new StringBuilder();

            String newLine = System.getProperty("line.separator");

 

            result.append(obj.getClass().getName());

            result.append(" Object {");

            result.append(newLine);

 

            // determine fields declared in this class only (no fields of

            // superclass)

            Field[] fields = obj.getClass().getDeclaredFields();

 

            // print field names paired with their values

            for (Field field : fields) {

                  result.append("  ");

                  try {

                        result.append(field.getName());

                        result.append(": ");

                        // requires access to private field:

                        result.append(field.get(obj));

                        result.append(",");

                  } catch (IllegalAccessException ex) {

                        System.out.println(ex);

                  }

            }

            result.append(newLine);

            result.append("}");

 

            return result.toString();

      }

}

No comments:

Post a Comment