logger
logger

Reputation: 2053

Shared multiple class for ToString implementation

I have multiple pojo classes using below code.

public class ToStringImpl {

public String toString(){
      StringBuilder result = new StringBuilder();
      String newLine = "\n";


      result.append( this.getClass().getName() );
      result.append( " Data {" );
      result.append(newLine);

      //determine fields declared in this class only (no fields of superclass)
      Field[] fields = this.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(this) );
        } catch ( IllegalAccessException ex ) {
          System.out.println(ex);
        }
        result.append(newLine);
      }
      result.append("}");

      return result.toString();
}

}

How do I call above class from different classes? Suppose I have pojo classes called customer, store, inventory

public class Customer {

private String name;
private String address;

...getter...setter...

public String toString(){

    ToStringImpl log = new ToStringImpl();
    //how do I pass different classes here?
    return log.toString();
}

}

public class Store {

private String logo;
private String type;

....getter...setter...
}

public class Inventory {

private boolean isAvailable;
private long index;

...getter...setter
}

for each class how do I pass different class? or if there are better way to do this? or would it be better to create toString as interface and implement it in each class and pass it as constructor?

Upvotes: 0

Views: 896

Answers (3)

Nathan Hughes
Nathan Hughes

Reputation: 96434

There is already a library that does this. Look up ToStringBuilder in the apache-commons library, your domain objects' toString method would look like:

@Override public String toString() {
    return ToStringBuilder.reflectionToString(this);
}

The best plan would seem to me to be to rip out the homegrown code and drop in apache-commons, or use Project Lombok. If you must reinvent this wheel then copying ToStringBuilder's example of using a static method and taking the object to print as a parameter would be reasonable.

The ToStringBuilder includes a feature to let you restrict which fields get printed, your own code should do something similar for the sake of your own sanity. The toString method is used to print out information for debugging and logging. If you just get all the fields like your posted code it will dump out the entire object's contents every time you call toString in a log entry and you will have something that's unreadable, it will fill up your logs and slow down your application writing all this information.

You are the consumer of the information here, make it something that's useful instead of being overwhelming.

Upvotes: 1

Michael Markidis
Michael Markidis

Reputation: 4191

What you can do is make the toString() method in the ToStringImpl class static. I wouldn't call it toString() though, change it to something like getClassString()

Example:

public static String getClassString(Object o)
{
    StringBuilder result = new StringBuilder();
    String newLine = "\n";

    result.append(o.getClass().getName());
    result.append(" Data {");
    result.append(newLine);

    // determine fields declared in this class only (no fields of
    // superclass)
    Field[] fields = o.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(o));
        }
        catch (IllegalAccessException ex)
        {
            System.out.println(ex);
        }
        result.append(newLine);
    }
    result.append("}");

    return result.toString();
}

Then in your POJO classes, call it with:

public String toString()
{
    // how do I pass different classes here?
    // by passing the 'this' reference
    return ToStringImpl.getClassString(this);
}

Upvotes: 3

killermenpl
killermenpl

Reputation: 23

When you override a method, for example Object#toString(), you only override it for that class. You can do one of the following:

  • Add your toString() to every class that might need it and then just call toString() on that object from wherever it is. (not recommended)
  • extend your ToStringImpl on every class you want to and call toString() on object.
  • Make ToStringImpl#toString() static and pass an object as argument (recommended), for example:

    public static void objectToString(Object ob){
       //your code here, just replace "this" with "ob"
    }
    

Upvotes: 0

Related Questions