> Java is pass-by-reference. Pass in object foo, call smash_with_hammer on foo in the called function, and the caller finds that his foo was smashed by a hammer when control returns to him

In agreement here, the state of the object changes according to a message passed to the object. In this case, the value we passed is a pointer to the object. We can't, however, change what object the pointer points to in Java, which is why I call it "pass by value". E.g., I can't do equiv of this Perl code.

sub bar { my $foo = Foo->new(a => "a"); foo(\$foo); }

sub foo { my $arg = shift; $$arg = Foo->new(a => "b"); }

On the other hand, in Perl even though I am passing a reference by value, I can still mutate the state of the object:

sub bar { my $foo = Foo->new(a => "a"); bar($foo); }

sub foo { my $foo = shift; $foo->set_a("b"); }

(Please excuse my Perl, I haven't written OO Perl in over a year now).

In any case, I think this is a pedantic point. Both of us agree that other than in few cases (algorithms/data structures that are difficult to express in a functional way), objects shouldn't be smashed by hammers: whether internal or external.

I also don't understand why Java's standard library authors didn't do what Scala did and provide both mutable and immutable versions of collections. Java 5+ added great lock free data, concurrent data structures, but much like they have a ConcurrentMap, they could have added a "ImmutableMap"/"ImmutableList" interfaces (especially given the fact that some data structures e.g., CopyOnWriteArrayList behave like this internally). I really like Scala's "functional objects": objects that upon receiving a messages, create new objects. In Java, an object may be final, but it will still (as you put it) "be smashed by a hammer" as long as the hammer smashing was invoked by a message. Same thing happens in C++ with const methods, in objects passed as const& references which contain objects that mutate their state upon a message being passed. Rich Hickey discusses this much better than I do in his famous talk: http://www.infoq.com/presentations/Value-Identity-State-Rich... (although I may not agree with all of his conclusions)

> seems like everything useful takes a StringBuffer instead of a String

That's a textbook example of premature optimization :-) The compiler will convert string concatenation to StringBuilder. See: https://gist.github.com/670577
It does makes sense to use a StringBuilder when you are doing concatenation inside a loop (and don't want the overhead of allocating a new StringBuilder inside), but otherwise there's no advantage to it.

(Oddly enough, in this example the default optimization level did not unroll the loop itself. OCaml, on the other hand, despite having a much more compiler-friendly type system than Java, doesn't perform the equivalent optimization on string concatenations with the '^' operator. I am pretty sure g++ will do both, despite C++ being lower-level and having weaker typing than OCaml and Java).

For another example of this kind of premature optimization, see people using inline in C++ code when the gcc/clang will have a much better idea than the developer on when to inline a function call and when not to :-)