Dimitri said:
s1.substring( 0, 1 ) + s1.substring( 5, 6 )
A dumb compiler would presumably create 3.1 transient strings
for
"" + s.charAt( i ) + s.charAt( j )
(.1 because "" would be interned and created at startup).
s.substring( i, i+1 ) + s.substring( j, j+1 )
would only create 2 transients.
It's worse than that, there are StringBuilders about. I have no idea why
javac produces such bad code, but that is what it does. See below.
For a more reasonable use of substring, use String.concat rather than
letting the compiler louse it up:
str.substring(i, i+1).concat(str.substring(j, j+1))
That, I believe, only produces two temporary String objects (but no
extra char[]s). String.valuOf(char[]) just creates one temporary char[].
StringBuilder will create a temporary StringBuilder object and an
oversized (a little) char[].
Rumour has it, a smart compiler can optimize transients away,
the question is how smart is "smart". My guess would be that
it will work for .substring() version and likely won't work
for .charAt() version (unless the optimizer can look past the
return value of charAt() and notice we're actually pulling out
substrings).
It looks as if one of the Sun 1.6 fcs byte -> machine code compilers
will be able to do the analysis (at least if you use
-XX:+DoEscapeAnalysis) but does not do stack allocation.
However, allocating short lived objects is surprisingly cheap.
The bulletproof way is, of course, appending to StringBuilder
as suggested upthread: you get a single transient (and much
"lighter") buffer instead of 2+ transient strings.
Strings will share the char[]. So it's creating a StringBuilder plus
char[] vs two Strings (and *no* temporary char[]s).
Of course, it all depends upon the implementation used.
Tom Hawtin
class X {
String fn(String str, int i, int j) {
return str.substring(i, i+1) + str.substring(j, j+1);
}
}
$ javap -c X
Compiled from "X.java"
class X extends java.lang.Object{
X();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>"

)V
4: return
java.lang.String fn(java.lang.String, int, int);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>"

)V
7: aload_1
8: iload_2
9: iload_2
10: iconst_1
11: iadd
12: invokevirtual #4; //Method
java/lang/String.substring

II)Ljava/lang/String;
15: invokevirtual #5; //Method
java/lang/StringBuilder.append

Ljava/lang/String

Ljava/lang/StringBuilder;
18: aload_1
19: iload_3
20: iload_3
21: iconst_1
22: iadd
23: invokevirtual #4; //Method
java/lang/String.substring

II)Ljava/lang/String;
26: invokevirtual #5; //Method
java/lang/StringBuilder.append

Ljava/lang/String

Ljava/lang/StringBuilder;
29: invokevirtual #6; //Method
java/lang/StringBuilder.toString

)Ljava/lang/String;
32: areturn
}