Counting String objects created by Java code
This Answer is to correct a misconception that is being put about by some of the other Answers:
For example:
The compiler might substitute x + y with a constant ("xyzabc"), though. @Binkan Salaryman
... and String object 4 [the String that corresponds to concatenation] can be computed by the compiler and turned into an interned constant as well. @dasblinkenlight
This is incorrect. The JLS states this:
15.18.1. String Concatenation Operator +
....
The String object is newly created (§12.5) unless the expression is a constant expression (§15.28).
In order to qualify as a constant expression, the variable names in the expression must be:
Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
where a "constant variable" is defined as:
A constant variable is a final variable of primitive type or type String that is initialized with a constant expression (§15.28).
In this example, neither x
or y
are final
so they are not constant variables. And even if they were final
, y
still wouldn't be a constant variable because of the use of the new
operator in its initialization.
In short, the Java compiler is not permitted to use an intern'd constant "xyzabc"
as the result of the concatenation expression.
If I added the following statement at the end:
System.out.println(x == "xyzabc");
it will always print false
... assuming that the compiler is conformant to the Java Language Specification.
By the end of the run there will be four String
objects:
- A
String
that corresponds to the interned"xyz"
literal - Its copy created by
new String("xyz")
- A
String
that corresponds to the interned"abc"
literal - A
String
that corresponds to concatenation"xyz" + "abc"
The real question is attributing some or all of these objects to your program. One can reasonably claim that as few as two or as many as four String
s are created by your code. Even though there are four String
objects in total, objects 1 and 3 may not necessarily be created by your code, because they are in a constant pool, so they get created outside your code's direct control.
Take a look at decompiled class and you'll see everything :) The answer should be:
- two strings (
"xyz"
and"abc"
) are only references to positions in constant pool so these ones are not created by your code - one string is created directly (
new String("xyz")
) string concatenation is optimised by compiler and changed to StringBuilder so the last string is created indirectly
public java.lang.String method(); descriptor: ()Ljava/lang/String; flags: ACC_PUBLIC Code: stack=3, locals=3, args_size=1 0: new #2 // class java/lang/String 3: dup 4: ldc #3 // String xyz 6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V 9: astore_1 10: ldc #5 // String abc 12: astore_2 13: new #6 // class java/lang/StringBuilder 16: dup 17: invokespecial #7 // Method java/lang/StringBuilder."<init>":()V 20: aload_1 21: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: aload_2 25: invokevirtual #8 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 28: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 31: astore_1 32: aload_1 33: areturn