Question

I used to use the implicit call of toString when wanting some debug info about an object, because in case of the object is null it does not throw an Exception.

For instance:

System.out.println("obj: "+obj);

instead of:

System.out.println("obj: "+obj.toString());

Is there any difference apart from the null case?
Can the latter case work, when the former does not?

Edit:
What exactly is done, in case of the implicit call?

Was it helpful?

Solution

There's little difference. Use the one that's shorter and works more often.

If you actually want to get the string value of an object for other reasons, and want it to be null friendly, do this:

String s = String.valueOf(obj);

Edit: The question was extended, so I'll extend my answer.

In both cases, they compile to something like the following:

System.out.println(new StringBuilder().append("obj: ").append(obj).toString());

When your toString() is implicit, you'll see that in the second append.

If you look at the source code to java, you'll see that StringBuilder.append(Object) looks like this:

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

where String.valueOf looks like this:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Now, if you toString() yourself, you bypass a null check and a stack frame and go straight to this in StringBuilder:

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

So...very similar things happens in both cases. One just does a little more work.

OTHER TIPS

As others have said - use the "" + obj method.

According to The Java Language Spec:

  • If the term is null, use "null"
  • Primitive types are converted using the boxed-type constructor new Boolean(X) or whatever
  • toString() is invoked (or equivalent)
  • if the result of toString() is null, use "null"
  • Concatenate the strings.

No difference except, like you say, the null safety. Always prefer the former to the latter.

Actually, if your invariant says the object should never be null, it doesn't matter. So it depends on whether or not you accept obj to be null.

It is quite easy to write a generic reference type.

class ref
{
  static public class Reference<T>
  {
    private T value;
    public Reference(T value) { set(value); }
    public Reference() { set(null); }
    public void set (T value) { this.value = value; }
    public T get () { return this.value; }
    public String toString() { return String.valueOf(this.value); }
  }

  static void fillString (Reference<String> str)
  {
    str.set("foo");
  }

  public static void main (String[] args)
  {
    Reference<String> str = new Reference<String>("");
    fillString(str);
    System.out.println (str);
  }
}

Running it gives the required output:

javac ref.java && java ref
foo
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top