I personally like to use method chaining and fluent interfaces and think these are great patterns, but in Java then tend to be implemented with a return this and that annoys me. It is generally assumed that methods modify the curent instance and return it, as highlighted in Wikipedia’s articles for method chaining:

possibly the current object itself

and fluent interface:

self-referential, where the new context is equivalent to the last context

This is also stressed in StringBuilder’s javadoc for all append methods:

Returns: a reference to this object.

It will thus be used that way:

StringBuilder b = new StringBuilder();
return b.toString();

The proper use of the API rely on the user carefully reading a comment on the javadoc. The API only states that it returns an instance of StringBuilder. Without reading the javadoc, assuming it returns new instances each time, a valid use could be:

StringBuilder b = new StringBuilder().append("Foo");
StringBuilder b1 = b.append("Bar1");
StringBuilder b2 = b.append("Bar2");

b1.toString(); // Expects "FooBar1"
b2.toString(); // Expects "FooBar2"

One having to jump to the javadoc makes the thing error prone. And will anyone look again at the documentation of all libraries after an update to check whether expectations changed with the new version? The way to chain method calls on the same object should simply never be implemented with a return this, it should be baked in the language itself to make the developer sure that it uses the instance it expects to find. In the case of StringBuilder I would like all instances to return void and be used like (dream code with arbitrary symbol for chaining):

StringBuilder b = new StringBuilder();

With that syntax no doubt the current instance is being internally modified and you still have to deal with the same instance.

Another valid solution would be to make the current instance immutable and return a new instance, possibly of a similar type, for every call (allowing code such as my second example). It may not make sense for StringBuilder since builders are not meant to be exposed outside of a single method and thus their scope is much more controlled, but it perfectly makes sense for collections as done in Clojure.