classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

2nd attempt at Re: The right way(tm) of writing toString() (Was: Re: [PA


From: Dalibor Topic
Subject: 2nd attempt at Re: The right way(tm) of writing toString() (Was: Re: [PATCH] Field position attribute handling)
Date: Sun, 30 Nov 2003 17:25:41 +0100
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.3) Gecko/20030312

Salut Etienne,

Etienne Gagnon wrote:
Dalibor Topic wrote:

e) use '+' to concatenate strings and objects

Rationale: Most Java compilers can optimize string concatenation by using string buffers. There is no need to do that task by hand. Using '+' allows you to write simpler code.



I partly disagree.  When you iterate through a collection, using "+" will
create one stringbuffer per iteration => bad.

So, I would in fact recommend using stringbuffers everywhere, unless the
toString() body holds on a single source line.

Thanks for pointing that out, I had forgot that.

f) don't use toString() on non-primitive fields. Use "field_name=" + field instead.


or
 sb.append("field_name=");
 sb.append(field);

yep.

g) don't write special code to handle fields being null


I think it also works for sb.append().

yes, it does.

Example code:

public class Test{
  private String field_1;
  private int field_2;

  public String toString() {
    return ("Test
            + "[field_1=" + field_1
            + ", field_2=" + field_2
            + ']');


This is a "logical" single line, so it fits the non-StringBuffer thing. But,
this does not work for LinkedList.toString(), for example.

Etienne

p.s. if performace of toString() doesn't matter that much, and we can use reflection


No, please! We want toString to be fast. It is part of the base functionality of Object(), so there is no reason to assume programmers will only use it for
debugging.

O.K., then I'll attempt to write down how to make toString() fast with StringBuffers.

so here's the updated version:

a) toString output should begin with the name of the class

Rationale: When a field is declared as having an interface type, or a non-final class, it is useful to know the exact type of the instance.

b) the rest of the string should be braced in '[' and ']'

Rationale: Visual separation makes it easier to separate the output string into its type information and information about the state of the particular instance.

c) different instances should have different string representations

Rationale: If two instances are not equal, then their string represenation should reflect that. The contents of all fields used in equals() should be part of the string representation of an instance.

d) fields that are used in the string representation must be named

Rationale: Explicitely naming fields removes ambiguities when a class contains several fields of the same type.

e) always use a StringBuffer

Rationale: While most Java compilers can optimize string concatenation by using string buffers automatically, that only works efficiently as long as the string representation can be generated within a single expression. If that's not the case, for example when iterating over a collection, most Java compilers create unnecessary temporary objects. Using a StringBuffer ensures that toString() works efficiently.

f) don't use toString() on non-primitive fields

Rationale: Calling toString() can fail if a field's instance in null, resulting in a NullPointerException being thrown inside toString(). Since toString() is usually used to provide debugging information, it must not fail. Using StringBuffer.append(Object) handles null automatically. So simply use StringBuffer's append method for "field_name=" and the field instance.

g) don't write special code to handle fields being null

  Rationale: follows from f).

h) re-use the StringBuffer on the stack

Rationale: In order to write as efficient code using StringBuffer as the good Java compilers, we need to reuse the StringBuffer instance on the stack. So instead of writing multiple append statements, try to use a single statement to perform all the work on the StringBuffer instance, including creation, calling append, and calling toString() on it.

Example code:

public class Test{
  private String field_1;
  private int field_2;

  public String toString() {
    return
        (new StringBuffer("Test[field_1=")).append(field_1)
        .append(",field_2=").append(field_2)
        .append(']')
        .toString();
  }
}

comments are welcome, as usual.

cheers,
dalibor topic





reply via email to

[Prev in Thread] Current Thread [Next in Thread]