Fundamentals 9 min read

Why Java Creates a Single String Object on Concatenation – Exploring Constant Folding

This article explains how Java’s compiler applies constant folding to compile‑time constants, turning string concatenations like "a"+"b"+"c" into a single String object, distinguishes compile‑time versus runtime constants, and demonstrates the impact on the constant pool and equality comparisons.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Why Java Creates a Single String Object on Concatenation – Exploring Constant Folding

First, consider a common interview question: how many String objects are created by the following code? String s = "a" + "b" + "c"; Decompiling the bytecode shows that only one String object is created.

The reason is that the compiler performs constant folding , evaluating compile‑time constant expressions during compilation and replacing them with the computed value.

A compile‑time constant must satisfy:

be declared final be of a primitive type or String be initialized at the point of declaration

be initialized with a constant expression

Examples:

final String s1 = "hello " + "Hydra";
final String s2 = UUID.randomUUID().toString() + "Hydra";

Here s1 is a compile‑time constant whose value is "hello Hydra", while s2 is not, because its initializer is not a constant expression; it is a runtime constant.

The compiled constant pool contains only the literal "hello Hydra" as a String entry; the value of s2 does not appear there.

Adding final can also affect class initialization. In the first run the class‑initialization block prints a message, while in the second run (with final on the static field) it does not.

public class IntTest1 {
    public static void main(String[] args) {
        System.out.println(a1.a);
    }
}
class a1 {
    static {
        System.out.println("init class");
    }
    public static int a = 1;
}

Running the code prints:

init class
1

Further examples demonstrate that a final String variable initialized with another variable is not a compile‑time constant, so the concatenated result is not folded:

final String h1 = "hello";
String h2 = "hello";
String s1 = h1 + "Hydra";
String s2 = h2 + "Hydra";
System.out.println(s1 == "helloHydra"); // true
System.out.println(s2 == "helloHydra"); // false

When a string is built from literals only, the compiler folds it; otherwise it creates a new object via StringBuilder, which explains why s2 == "ab" yields false while s3 == "ab" yields true in the following example:

String s1 = "a";
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab"); // false
System.out.println(s3 == "ab"); // true

The article also lists the kinds of expressions that the Java Language Specification considers constant expressions, such as literals, casts, unary operators (excluding ++ and --), binary arithmetic operators, and shift operators.

Finally, it notes that literals are stored in the constant pool, and that the null literal can be assigned to any reference type.

All code was tested on Java 1.8.0_261‑b12.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaJVMconstant foldingString InterningCompile-time Constants
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.