Strings and Text
|
This section documents the current Java release line, with Java 25 LTS as the reference point (no specific patch version is pinned), as published at the Java developer portal, the Java Tutorials, and the Java SE API specification — which are the references these pages are written and verified against. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. This section’s bibliography lists the reference material consulted while preparing these pages. |
Java text is a String — an immutable sequence of UTF-16 char values. StringBuilder handles incremental
construction, text blocks cover multi-line literals, and String.format templates output. The consulted books
predate text blocks (Java 15) and the strip / isBlank / formatted methods (Java 11+), so this page follows
the current
String API.
Immutability and the String Pool
A String’s contents never change: every "modifying" method returns a new object. String literals are
interned in a per-JVM string pool, so identical literals share one instance. Compare contents with
`equals
(or equalsIgnoreCase), never with ==, which compares references. Equal strings always return the same
hashCode.
String a = "cat"; // literal -> interned in the string pool
String b = "cat"; // the same pooled instance
String c = new String("cat"); // an explicit, separate object
System.out.println(a == b); // true -- one pooled reference
System.out.println(a == c); // false -- different objects
System.out.println(a.equals(c)); // true -- same characters
System.out.println(a.equalsIgnoreCase("CAT")); // true
String shout = a.toUpperCase(); // a NEW string; 'a' is untouched
System.out.println(a + " " + shout); // cat CAT
System.out.println(a.hashCode() == c.hashCode()); // true
String pooled = c.intern(); // canonical pooled instance for "cat"
System.out.println(a == pooled); // true
See the Java Tutorials on comparing strings and the JLS on string literals.
Everyday String Methods
String exposes read-only queries and transformation methods, each returning a new string. split and the
regex-taking overloads of replaceAll are covered on
Regular Expressions; note that
split takes a regex, so a literal dot must be escaped.
String s = " Hello, world ";
System.out.println(s.length()); // 15
System.out.println(s.strip()); // "Hello, world" -- Unicode-aware trim
System.out.println(s.isBlank()); // false
System.out.println("Hello".charAt(0)); // H
System.out.println("Hello".indexOf('l')); // 2
System.out.println("Hello".substring(1, 4)); // ell (end index exclusive)
System.out.println("Hello".replace('l', 'L')); // HeLLo
System.out.println("=".repeat(8)); // ========
System.out.println("a.b.c".split("\\.").length); // 3
"abc".chars() // IntStream of char values
.forEach(ch -> System.out.print((char) ch + " ")); // a b c
Full method list: the
String Javadoc and the
Tutorials' Manipulating Characters in a
String.
char vs. Unicode Code Points
A char is a single 16-bit UTF-16 code unit. Characters outside the Basic Multilingual Plane (many emoji, some
CJK) are a surrogate pair — two char values — so length counts code units, not characters. Use
codePointAt,
codePointCount, and
codePoints
for character-accurate work; the code-point helpers live on
Character.
String s = "A😀B"; // 'A', emoji U+1F600, 'B'
System.out.println(s.length()); // 4 -- UTF-16 code units
System.out.println(s.codePointCount(0, s.length())); // 3 -- actual characters
s.codePoints()
.mapToObj(Character::toString)
.forEach(System.out::println); // A / the emoji / B
Building Strings with StringBuilder
Repeated ` on `String` inside a loop allocates a fresh object each iteration -- quadratic work.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/StringBuilder.html[`StringBuilder`] is a
single growable buffer; a lone ` between two values is fine (the compiler handles it), the loop is the
problem.
// Anti-pattern: O(n^2) copying
String slow = "";
for (int i = 0; i < 1_000; i++) {
slow += i + ",";
}
// Preferred: one buffer, O(n)
var sb = new StringBuilder();
for (int i = 0; i < 1_000; i++) {
sb.append(i).append(',');
}
sb.insert(0, "[").append(']');
String fast = sb.toString();
System.out.println(fast.length());
StringBuffer is the
older synchronized equivalent; prefer StringBuilder unless a buffer is genuinely shared across threads. More
in the Tutorials' The StringBuilder Class.
Text Blocks
A text block is a string literal delimited by """ and a newline. Incidental whitespace — the common
left-indentation shared with the closing delimiter — is stripped, so the block can stay indented with its
code. A trailing \ suppresses the line break; \s preserves one trailing space.
String json = """
{
"name": "Ada",
"roles": ["admin", "dev"]
}
"""; // trailing newline kept (closing """ on its own line)
String sql = """
SELECT id, name
FROM users
WHERE active = true"""; // no trailing newline
String joined = """
The quick brown \
fox jumps"""; // "The quick brown fox jumps"
String trailing = """
key =\s
value"""; // the space before the newline is kept
Reach for text blocks for embedded JSON, SQL, HTML, or multi-line messages; a plain literal is still better for one line. See the text blocks guide, JEP 378, and the JLS on text blocks.
Formatting Text
String.format
and the instance method formatted build a string from a format string and arguments;
String.join
concatenates with a separator. printf writes the same format directly to a stream.
String name = "Ada";
int score = 92;
String line1 = String.format("%s scored %d out of 100", name, score);
String line2 = "%s scored %d out of 100".formatted(name, score); // identical result
String csv = String.join(", ", "x", "y", "z"); // "x, y, z"
String rows = String.join("\n", java.util.List.of("r1", "r2", "r3"));
System.out.printf("%-8s|%6.2f%n", name, 3.14159); // "Ada | 3.14"
The full conversion syntax (flags, width, precision, argument indexes, locale) lives in
java.util.Formatter.
The Tutorials cover this under Strings.
See Also
-
Primitive Types & Variables —
char, escapes, and the primitive conversions behindchars(). -
Regular Expressions — the regex engine behind
split,matches, andreplaceAll. -
Streams & Collectors — consuming
chars()andcodePoints()as streams, andCollectors.joining.