43

We have a lot of objects for which we like to implement a simple toString to output attributes of the object. Some of these attributes may be complex objects themselves.

Is there any standard, or simply just a best practice for a style? I'm thinking something like:

[SimpleClassName] { prop1:value, prop2:value }

In which case a nested value would look like:

[SimpleClassName] { prop1:value, prop2:[NestedObject] { prop3:value}}

We are using Java but I find myself asking the same question in most languages!

Nicole
  • 32,841
  • 11
  • 75
  • 101
  • 3
    Hint: an IDE like Eclipse can generate a `toString()`. Explore the *Source* menu. Timesaver! – BalusC Oct 16 '10 at 02:15
  • 1
    I think a real timesaver would be to use a debugger. You can just break execution at any point, then print all the information you need about the available objects, get a stack track, make any changes required, and then continue. All without bloating your code with toString methods and traces. Why bother then the debugger does it all for you, for every object? – Joony Oct 16 '10 at 07:39
  • Java SE7 documentation gives a pretty good description on what toString() should do. [Here](https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#toString()). – carloswm85 Sep 30 '20 at 22:03

8 Answers8

35

I think the format produced by Guava's MoreObjects.toStringHelper() is pretty nice, but it's mainly just good to have some consistent format that you use:

public String toString() {
  return Objects.toStringHelper(this)
      .add("prop1", prop1)
      .add("prop2", prop2)
      .toString();
}

// Produces "SimpleClassName{prop1=foo, prop2=bar}"
facundofarias
  • 2,973
  • 28
  • 27
ColinD
  • 108,630
  • 30
  • 201
  • 202
31

Personally, I find the mix of [] and {} not so easy to get an immediate view of the hierarchy.

I like this format (and I've seen it being used in a number of places):

SimpleClassName[prop1=value, prop2=value]
SimpleClassName[prop1=value, prop2=NestedObject[prop3=value]]

There's also the possibility to add an identifier with @, for example the default style for the commons-lang ToStringBuilder does that (using its own example):

Person@182f0db[name=John Doe,age=33,smoker=false]
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Wouter Coekaerts
  • 9,395
  • 3
  • 31
  • 35
  • I like it, but any idea how this meshes with toString used by various frameworks and other open source projects? – Nicole Oct 15 '10 at 22:58
  • 1
    +1, Good to know that eclipse by default generates `toString` method in that format. – G. Demecki Sep 11 '14 at 06:30
  • I like this one, though a variation I prefer is like the Java Tutorial where they do not put spaces after commas. While it's more dense, it has the advantage of being able to see strings without having to add quote chars, if that makes sense. Class.getSimpleName() is useful instead of hard-coding, as is Arrays.toString() for array-based variables. – Matthew Cornell May 17 '16 at 14:16
  • The linkt to *the default style* seems to be dead. – JojOatXGME Jul 03 '20 at 23:11
4

json syntax seems to fit pretty well since it was designed specifically to represent complex objects as strings

Person = {
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": 
    {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": "10021"
    },
    "phoneNumber": 
    [
        {
            "type": "home",
            "number": "212 555-1234"
        },
        {
            "type": "fax",
            "number": "646 555-4567"
        }
    ]
}
Brad Mace
  • 27,194
  • 17
  • 102
  • 148
3

Not a direct answer to the question, however below would be a time saver during initial development:

Disclaimer: Apache Commons library is used.

  1. Add a new Eclipse template called xreflect in Java > Editor > Templates; Add below into its pattern textarea:
// ---------- template start ----------- //
${:import(org.apache.commons.lang.builder.EqualsBuilder,org.apache.commons.lang.builder.HashCodeBuilder,org.apache.commons.lang.builder.ReflectionToStringBuilder)}
/*
 * (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(
        final Object pObj) {
    return EqualsBuilder.reflectionEquals(this, pObj);
}

/*
 * (non-Javadoc)
 * @see java.lang.Object#toString()
 */
@Override
public String toString() {
    return ReflectionToStringBuilder.toString(this);
}

/*
 * (non-Javadoc)
 * @see java.lang.Object#hashCode()
 */
@Override
public int hashCode() {
    return HashCodeBuilder.reflectionHashCode(this);
}
// ---------- template end ----------- //
  1. Give OK, OK
  2. Just go to the end of a Java class, type xreflect and press Ctrl + Space to autofill equals(), toString() and hashCode() methods automatically.
KrishPrabakar
  • 2,824
  • 2
  • 31
  • 44
1

Is there any standard, or simply just a best practice for a style?

No. The "best" output for a toString() method is determined by what you want to use it for. Is it for serializing the object state in a form that allows it to be deserialized? Is it for creating debug messages? Is it for rendering the object for display to end-users?

(Note that in Java, the toString() method can be used for either purpose. Using toString() for / in end-user messages has problems ... but people do it anyway.)

If you want to develop an in-house style for your debug/logging toString() methods, that's fine. But unless there was a requirement for this, I wouldn't bother. IMO, it is effort that could better be spent elsewhere.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

If your objects have something that might be useful as an identifier, I'd implement something like your second example:

[SimpleClassName:id] { prop1:value, prop2:[NestedObject:id] { prop3:value }}

Where the id is whatever makes sense for that object to be an identifier - the name for the canonical Person object, a primary key for an object from a database, etc.

zigdon
  • 14,573
  • 6
  • 35
  • 54
0

Since you asked about what other open source projects to, here's how jEdit does it, which is similar to Wouter's:

BufferChanging[what=BUFFER_CHANGING,source=org.gjt.sp.jedit.EditPane[active,global]]
Brad Mace
  • 27,194
  • 17
  • 102
  • 148
0

check out phps print_r($obj, true) or also serialize() could work, dont know exactly for what its needed for. jsons is also a clean solution, especially if u want to import the data in javascript environbments

rthrwht
  • 21
  • 1