00:00

String in Java – Creation, String Pool, Immutability and Methods

A String in Java is an object that represents an immutable sequence of characters. Strings are used everywhere, from user input and file contents to JSON, URLs and log messages, so Java gives them special support: literal syntax, a shared string pool, the + operator for concatenation and a rich set of methods.

This tutorial covers creating strings, the string pool, immutability and why it matters, comparing strings correctly, the most useful methods, text blocks, and efficient concatenation.

1. Creating Strings and the String Pool

Java String constant pool in heap memory

String literals are stored in the string pool (part of the heap). When the same literal appears again, the JVM reuses the pooled object instead of creating a new one. new String(...) always creates a separate object:

StringCreation.java
public class StringCreation {
    public static void main(String[] args) {
        String a = "Java";                 // literal: stored in the String pool
        String b = "Java";                 // reuses the same pooled object
        String c = new String("Java");     // forces a new object on the heap
        String d = c.intern();             // returns the pooled instance

        System.out.println("a == b      : " + (a == b));        // same object
        System.out.println("a == c      : " + (a == c));        // different objects
        System.out.println("a.equals(c) : " + a.equals(c));     // same content
        System.out.println("a == d      : " + (a == d));

        char[] chars = {'J', 'V', 'M'};
        String fromChars = new String(chars);
        String fromValue = String.valueOf(42);
        String textBlock = """
                {
                  "site": "JavaByTechie"
                }""";                        // text block (Java 15)
        System.out.println(fromChars + " " + fromValue);
        System.out.println(textBlock);
    }
}
Output
a == b      : true
a == c      : false
a.equals(c) : true
a == d      : true
JVM 42
{
  "site": "JavaByTechie"
}
  • Literals with the same content share one pooled object, so a == b is true.
  • new String("Java") creates a distinct object, so a == c is false; avoid it in normal code.
  • intern() returns the pooled copy of a string's content.
  • Text blocks (""", Java 15) make multi-line strings such as JSON, SQL and HTML readable.

2. Strings Are Immutable

Once created, a String object never changes. Methods like toUpperCase() and replace() return new strings:

Immutability.java
public class Immutability {
    public static void main(String[] args) {
        String s = "hello";
        s.toUpperCase();                    // result ignored: s is unchanged
        System.out.println(s);

        String upper = s.toUpperCase();     // a NEW string is returned
        System.out.println(upper + " / original still: " + s);

        String t = s;
        s = s + " world";                   // s now points to a new object
        System.out.println("t = " + t + ", s = " + s);
    }
}
Output
hello
HELLO / original still: hello
t = hello, s = hello world

Why immutability matters:

  • Pooling: sharing is safe only because nobody can change a pooled string.
  • Security: file paths, URLs and class names cannot be altered after validation.
  • Thread safety: strings can be shared between threads without synchronization.
  • Hashing: the hash code is cached, making strings fast and reliable HashMap keys.

3. Comparing Strings: == vs equals()

ComparisonChecksUse
a == bSame object (reference)Almost never for strings
a.equals(b)Same charactersContent equality
a.equalsIgnoreCase(b)Same characters, ignoring caseUser input, codes
a.compareTo(b)Lexicographic order (negative, 0, positive)Sorting
Objects.equals(a, b)Content, null-safeWhen either may be null

Write "admin".equals(role) rather than role.equals("admin") to avoid a NullPointerException when role is null.

4. Commonly Used String Methods

CommonMethods.java
import java.util.Arrays;

public class CommonMethods {
    public static void main(String[] args) {
        String s = "  Java By Techie  ";
        String t = s.strip();
        System.out.println("strip()            : [" + t + "]");
        System.out.println("length()           : " + t.length());
        System.out.println("charAt(5)          : " + t.charAt(5));
        System.out.println("indexOf(\"By\")      : " + t.indexOf("By"));
        System.out.println("substring(5, 7)    : " + t.substring(5, 7));
        System.out.println("toLowerCase()      : " + t.toLowerCase());
        System.out.println("replace(' ', '-')  : " + t.replace(' ', '-'));
        System.out.println("contains(\"Tech\")   : " + t.contains("Tech"));
        System.out.println("startsWith(\"Java\") : " + t.startsWith("Java"));
        System.out.println("split(\" \")         : " + Arrays.toString(t.split(" ")));
        System.out.println("isBlank() of \"  \"  : " + "  ".isBlank());
        System.out.println("repeat(3)          : " + "ab".repeat(3));
        System.out.println("join               : " + String.join(", ", "Java", "Spring", "Kafka"));
        System.out.println("equalsIgnoreCase   : " + "JAVA".equalsIgnoreCase("java"));
        System.out.println("compareTo          : " + "apple".compareTo("banana"));
        System.out.println("formatted          : " + "%s scored %d".formatted("Asha", 92));
        System.out.println("chars().count()    : " + t.chars().filter(Character::isUpperCase).count() + " uppercase");
    }
}
Output
strip()            : [Java By Techie]
length()           : 14
charAt(5)          : B
indexOf("By")      : 5
substring(5, 7)    : By
toLowerCase()      : java by techie
replace(' ', '-')  : Java-By-Techie
contains("Tech")   : true
startsWith("Java") : true
split(" ")         : [Java, By, Techie]
isBlank() of "  "  : true
repeat(3)          : ababab
join               : Java, Spring, Kafka
equalsIgnoreCase   : true
compareTo          : -1
formatted          : Asha scored 92
chars().count()    : 3 uppercase
CategoryMethods
Inspectlength, charAt, isEmpty, isBlank (11), chars
SearchindexOf, lastIndexOf, contains, startsWith, endsWith, matches
Extractsubstring, split, lines (11), toCharArray
TransformtoUpperCase, toLowerCase, trim, strip (11), replace, replaceAll, repeat (11), indent (12)
Buildconcat, join, format, formatted (15), valueOf

strip() removes all Unicode whitespace, while the older trim() removes only characters up to U+0020.

5. Concatenation and Performance

The + operator is fine for a few pieces; the compiler optimises it. In loops, however, each += creates a new string and copies all previous characters. Use StringBuilder instead:

ConcatPerformance.java
public class ConcatPerformance {
    public static void main(String[] args) {
        int n = 20_000;

        long start = System.nanoTime();
        String s = "";
        for (int i = 0; i < n; i++) s += "x";            // creates a new String every time: O(n^2)
        long plusMs = (System.nanoTime() - start) / 1_000_000;

        start = System.nanoTime();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) sb.append("x");      // appends in place
        String built = sb.toString();
        long sbMs = (System.nanoTime() - start) / 1_000_000;

        System.out.println("Same result: " + s.equals(built));
        System.out.println("StringBuilder faster: " + (sbMs < plusMs));
    }
}
Output
Same result: true
StringBuilder faster: true
ClassMutable?Thread-safe?Use for
StringNoYes (immutable)Fixed text, keys, constants
StringBuilderYesNoBuilding text in one thread (most cases)
StringBufferYesYes (synchronized)Legacy code shared across threads

6. Under the Hood

  • Since Java 9, compact strings store Latin-1 text in one byte per character instead of two, roughly halving memory for most strings.
  • Since Java 7, the string pool lives in the main heap, so pooled strings can be garbage-collected.
  • String is final, so it cannot be subclassed and its behaviour is guaranteed.

7. Summary

  • A String is an immutable sequence of characters; methods return new strings.
  • Literals are pooled and shared; new String() creates separate objects.
  • Compare content with equals(), never with ==.
  • Use text blocks for multi-line text and StringBuilder for building strings in loops.

Related Tutorials