5.2 Compile-Time Versus Runtime Resolution of Strings
For optimized use of
Strings, you should know the difference between
compile-time resolution of
Strings and runtime creation. At compile time,
Strings are resolved to eliminate the
concatenation operator if possible. For example, the line:
String s = "hi " + "Mr. " + " " + "Buddy";
is compiled as if it read:
String s = "hi Mr. Buddy";
However, suppose you defined the String using a
StringBuffer:
String s = (new StringBuffer( )).append("hi ").
append("Mr. ").append(" ").append("Buddy").toString( );
Then the compiler cannot resolve the String at
compile time. The result is that the String is
created at runtime along with a temporary
StringBuffer. The version that can be resolved at
compile time is more efficient. It avoids the overhead of creating a
String and an extra temporary
StringBuffer, as well as avoiding the runtime cost
of several method calls.
However, when an expression involving
String concatenation cannot be resolved at compile
time, the concatenation must execute at runtime. This causes extra
objects to be generated. For example, consider the following method:
public String sayHi(String title, String name)
{
return "hi " + title + " " + name;
}
The String generated by this method cannot be
resolved at compile time because the variables can have any value.
The compiler is free to generate code to optimize the
String creation, but it does not have to.
Consequently, the String-creation line could be
compiled as:
return (new StringBuffer( )).append("hi ").
append(title).append(" ").append(name).toString( );
This is optimal, creating only two objects. On the other hand, the
compiler could also leave the line with the default implementation of
the concatenation operator, which is equivalent to:
return "hi ".concat(title).concat(" ").concat(name);
This last implementation creates two intermediate
String objects that are then thrown away, and
these are generated every time the method is called.
So, when the String can be fully resolved at
compile time, the concatenation operator is more efficient than using
a StringBuffer. But when the
String cannot be resolved at compile time, the
concatenation operator is less efficient than using a
StringBuffer.
One
further point is that using the String constructor
in a String definition forces a runtime string
creation:
String s = new String("hi " + "Mr. " + " " + "Buddy");
This is compiled as:
String s = new String("hi Mr. Buddy");
This line uses the compile-time resolved string as a parameter for
the String constructor to create a new
String object at runtime. The new
String object is equal but not identical to the
original string:
String s = new String("hi Mr. Buddy");
s = = "hi Mr. Buddy"; //is false
s.equals("hi Mr. Buddy"); //is true
|