I have the following test code:
public class StringLiteralTest {
static void testPrefix() {
int i = 0;
String prefixConcat = "a" + "b" + i;
}
static void testSuffix() {
int i = 0;
String suffixConcat = i + "c" + "d";
}
}
The generated bytecode is:
Compiled from "StringLiteralTest.java"
public class StringLiteralTest {
public StringLiteralTest();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
static void testPrefix();
Code:
0: iconst_0
1: istore_0
2: new #15 // class java/lang/StringBuilder
5: dup
6: ldc #17 // String ab
8: invokespecial #19 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
11: iload_0
12: invokevirtual #22 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
15: invokevirtual #26 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
18: astore_1
19: return
static void testSuffix();
Code:
0: iconst_0
1: istore_0
2: new #15 // class java/lang/StringBuilder
5: dup
6: iload_0
7: invokestatic #35 // Method java/lang/String.valueOf:(I)Ljava/lang/String;
10: invokespecial #19 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
13: ldc #41 // String c
15: invokevirtual #43 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: ldc #46 // String d
20: invokevirtual #43 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: invokevirtual #26 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: astore_1
27: return
}
In testPrefix()
, the expression "a" + "b"
is combined into the string literal "ab"
by the Java compiler, but in testSuffix()
, the expression "c" + "d"
is not combined at compile-time.
Why can't the compiler combine the String literals in the second method?
The source file was compiled with the default Oracle JDK 8 javac.
String literalsThe code concatenates the smaller strings to create the long string literal. The parts are concatenated into a single string at compile time.
Concatenation is the process of combining two or more strings to form a new string by subsequently appending the next string to the end of the previous strings. In Java, two strings can be concatenated by using the + or += operator, or through the concat() method, defined in the java. lang. String class.
concat() Method util package concatenates one string to the end of another string. This method returns a string with the value of the string passed into the method, appended to the end of the string.
Concatenation of two Strings If you concatenate Stings in loops for each iteration a new intermediate object is created in the String constant pool. This is not recommended as it causes memory issues.
Because the string concatenation operator (+) is syntactically left associative:
For example, the expression:
a + b + c
is always regarded as meaning:
(a + b) + c
Admittedly, if b
and c
are strings, the expression is equivalent to a + (b + c)
. So a compiler could do what you suggest in that specific situation, but it is not mandated by the specification...
String suffixConcat = i + "c" + "d";
is equivalent to
String suffixConcat = (i + "c") + "d";
You could argue that it is equivalent to this expression
String suffixConcat = i + ("c" + "d");
which will be optimized to
String suffixConcat = i + "cd";
I think, this it the reason why the byte code does not include that optimization is in Language specification (15.18.1. String Concatenation Operator +):
The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).
In other words, (i + "c")
has to be new string, and (i + "c") + "d"
again has to be a new string.
However, a JIT compiler could internally apply the optimization as it does not change the observable semantics.
This isn't a great answer.
The order of addition is defined and takes place from the left.
This:
public static void main (String[] args)
{
String x= "X" + 1 + 2;
String y= 1 + 2 + "Y";
System.out.println(x);
System.out.println(y);
}
Has expected output
X12
3Y
So I'm guessing that the compiler spots that literal plus literal can be optimized to 'long literal' but doesn't recognise that reordering the operations would have the same outcome so the verbose code produced.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With