Bruno Gasparotto
Bruno Gasparotto

Reputation: 671

Avoiding memory inefficiency when overring toString() of a common POJO using StringBuilder

I'm developing a project that all my POJOs must have they toString() inherited from Object class overridden.

Consider the immutable class below:

public final class SomeActivity {
    private final int id;
    private final String name;
    private final String description;
    private final DateTime startDate;
    private final DateTime endDate;
    private final String note;

    // Constructors and getters

    // My future implementation of toString
}

My objective when overriding toString() is to achieve and output similar of the output below (using test values of all SomeActivity class fields):

[Id: 1, Name: Read a book, Description: Trying to discover how to build a plane, StartDate: 17/10/2013, EndDate: 15/11/2013, Note: I really need this]

So, I have two solutions in mind:

1 - Concatenate Strings

As far I know, String is a immutable class. (refer to the javadoc), so, if I implement a method to receive such output, I may have many objects being created because of my concatenations:

@Override
public String toString() {
    String s = "[Id: " + id + 
            ", Name: " + name + 
            ", Description: " + description + 
            ", StartDate: " + startDate + 
            ", EndDate: " + endDate + 
            ", Note: " + note + 
            "]";
}

2 - Using StringBuilder

With StringBuilder approach, in theory, I would have less objects being instantiated instead of the "concatenation approach". But notice new StringBuilder and toString() calls of the code below:

@Override
public String toString() {
    StringBuilder builder = new StringBuilder();
        builder.append("[Id: ").append(id)
                .append(", Name: ").append(name)
                .append(", Description: ").append(description)
                .append(", StartDate: ").append(startDate)
                .append(", EndDate: ").append(endDate)
                .append(", Note: ").append(note)
                .append("]");

        return builder.toString();
}

This second alternative, is really the best possible? Or is there another approach that I should adopt? Consider those toString methods being called from a loop statement.

Unfortunately, I'm not very familiar with memory tests, so if is possible to write tests for that, I'll be very glad to know about that.

Thanks in advance.

Upvotes: 5

Views: 1469

Answers (2)

rai.skumar
rai.skumar

Reputation: 10677

ToStringBuilder from apache commons has a very clean way to generate toString implementation.

   public class Person {
    String name;
    int age;
    boolean smoker;
   } 


   public String toString() {
     return new ToStringBuilder(this).
       append("name", name).
       append("age", age).
       append("smoker", smoker).
       toString();
   }
 }

This will produce a toString of the format:

Person@7f54[name=Stephen,age=29,smoker=false]

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502686

As far I know, String is a immutable class. (refer to the javadoc), so, if I implement a method to receive such output, I may have many objects being created because of my concatenations:

Nope. As you're performing all the concatenation in a single large expression, the compiler will pretty much just create the StringBuilder-equivalent code for you.

But notice new StringBuilder and toString() calls of the code below:

Um, yes - and? It would be unusual to create a toString method which used various different field values but didn't create a string.

There's no memory leak here. Yes, you'll create a StringBuilder and String, but they'll be garbage collected appropriately.

Feel free to use either of these forms - or String.format, perhaps - whatever you find simplest to read. If you use the first form, I'd reformat it to have one description and one field value per line:

return "["
    + "Id: " + id 
    + ", Name: " + name 
    + ", Description: " + description
    + ", StartDate: " + startDate 
    + ", EndDate: " + endDate 
    + ", Note: " + note
    + "]";

At this point it looks more like the second form, in terms of readability and ease of adding/removing fields.

Upvotes: 8

Related Questions