strings: Java Strings deep dive companion code (pool/intern, indy concat vs StringBuilder JMH, text blocks, string templates)

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KqJyCidz3ZgRyHABv2GVJh
This commit is contained in:
Claude
2026-09-30 19:06:34 +00:00
parent 97e7352f45
commit 366579f478
22 changed files with 563 additions and 0 deletions
+9
View File
@@ -0,0 +1,9 @@
literal == literal : true
literal == new String : false
literal.equals(new String) : true
literal == c.intern() : true
constant + literal == "hello" : true
runtime concat == "hello" : false
runtime concat.intern() == "hello": true
built "java".intern() == the built instance : false
built unseen string .intern() == the built instance: true
+30
View File
@@ -0,0 +1,30 @@
--- closing delimiter on its own line, aligned with the text ---
{\n
.."id":.1\n
}\n
--- closing delimiter right after the last line (no final newline) ---
{\n
.."id":.1\n
}
--- closing delimiter 2 columns left of the text: 2 spaces of indentation survive ---
..left\n
--- trailing spaces are stripped, but \s and \040 survive ---
x....\n
y.\n
--- backslash at end of line joins the lines ---
one.line\n
--- escapes are processed after indentation is stripped ---
tab: |\n
--- double quotes need no escape; only a run of three does ---
say."hi".and."""\n
two identical text blocks are the same pooled instance: true
equals the hand-written literal: true
--- formatted() is the built-in way to interpolate ---
Hello,.Ann!.You.are.30.\n
+7
View File
@@ -0,0 +1,7 @@
iteration 0: length=1 value=0
iteration 1: length=2 value=01
iteration 2: length=3 value=012
iteration 3: length=4 value=0123
iteration 4: length=5 value=01234
characters copied in total across the loop results: 15
n=20000: final length=20000, characters in all intermediate strings=200010000
@@ -0,0 +1,25 @@
$ javac ConcatShapes.java && javap -c -p ConcatShapes (method one)
public static java.lang.String one(java.lang.String, int);
Code:
0: aload_0
1: iload_1
2: invokedynamic #7, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
7: areturn
$ javac -XDstringConcat=inline ConcatShapes.java && javap -c -p ConcatShapes (method one)
public static java.lang.String one(java.lang.String, int);
Code:
0: new #7 // class java/lang/StringBuilder
3: dup
4: invokespecial #9 // Method java/lang/StringBuilder."<init>":()V
7: ldc #10 // String user=
9: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: aload_0
13: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: ldc #16 // String n=
18: invokevirtual #12 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: iload_1
22: invokevirtual #18 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
25: invokevirtual #21 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
28: areturn
+6
View File
@@ -0,0 +1,6 @@
$ javap -c -v ConcatShapes | grep -A3 BootstrapMethods
BootstrapMethods:
0: #39 REF_invokeStatic java/lang/invoke/StringConcatFactory.makeConcatWithConstants:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;
Method arguments:
#37 user=\u0001 n=\u0001
InnerClasses:
@@ -0,0 +1,11 @@
$ javac StringTemplate.java
src/broken/StringTemplate.java:4: error: illegal escape character
System.out.println(STR."Hello, \{name}");
^
1 error
$ javac --enable-preview --release 25 StringTemplate.java
src/broken/StringTemplate.java:4: error: illegal escape character
System.out.println(STR."Hello, \{name}");
^
1 error
+4
View File
@@ -0,0 +1,4 @@
bool CompactStrings = true {pd product} {default}
bool OptimizeStringConcat = true {C2 product} {default}
uintx StringTableSize = 65536 {product} {default}
bool UseStringDeduplication = false {product} {default}
+16
View File
@@ -0,0 +1,16 @@
Benchmark (loop) Mode Cnt Score Error Units
ConcatBenchmark.explicitBuilder N/A avgt 10 20.838 ± 2.629 ns/op
ConcatBenchmark.formattedMethod N/A avgt 10 164.278 ± 12.164 ns/op
ConcatBenchmark.plusExpression N/A avgt 10 20.448 ± 7.264 ns/op
ConcatBenchmark.plusLatin1 N/A avgt 10 15.791 ± 4.953 ns/op
ConcatBenchmark.plusUtf16 N/A avgt 10 23.185 ± 4.275 ns/op
ConcatBenchmark.stringFormat N/A avgt 10 285.885 ± 133.980 ns/op
LoopConcatBenchmark.loopBuilder 100 avgt 5 270.251 ± 128.322 ns/op
LoopConcatBenchmark.loopBuilder 1000 avgt 5 2268.140 ± 888.134 ns/op
LoopConcatBenchmark.loopBuilder 10000 avgt 5 24468.200 ± 8712.080 ns/op
LoopConcatBenchmark.loopBuilderPresized 100 avgt 5 194.101 ± 168.069 ns/op
LoopConcatBenchmark.loopBuilderPresized 1000 avgt 5 1682.224 ± 135.261 ns/op
LoopConcatBenchmark.loopBuilderPresized 10000 avgt 5 20622.063 ± 16702.078 ns/op
LoopConcatBenchmark.loopPlusEquals 100 avgt 5 2021.521 ± 648.577 ns/op
LoopConcatBenchmark.loopPlusEquals 1000 avgt 5 73764.547 ± 11968.016 ns/op
LoopConcatBenchmark.loopPlusEquals 10000 avgt 5 8939940.357 ± 2388632.875 ns/op
+4
View File
@@ -0,0 +1,4 @@
-------------------------------------------------------------------------------
Test set: com.ankurm.strings.StringBehaviourTest
-------------------------------------------------------------------------------
Tests run: 8, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.252 s -- in com.ankurm.strings.StringBehaviourTest