Strings & Text Blocks
Immutable String, StringBuilder, Text Blocks, format, encoding
What's Special About Strings in Java
Use cases: log messages, HTTP request/response, SQL building, template rendering, CLI argument handling. Java's String is designed for "safe + fast" — it is immutable, cached in the literal pool, and stays valid as a Map key, so it flows through systems especially often.
String Is Immutable + the String Literal Pool
A String's content cannot change after creation: any "modifying" operation (replace, trim, toLowerCase…) returns a new object. Identical literals in source (like "hello") are pooled by the JVM into one object, saving memory. new String("hello") forces a new object, bypassing the pool — **don't use new String** unless you have a specific reason.
// StringIdentity.java
public class StringIdentity {
public static void main(String[] args) {
String a = "hello";
String b = "hello"; // same pooled object
String c = new String("hello"); // new object, bypasses the pool
String d = c.intern(); // explicitly interned, gets the pooled object again
System.out.println(a == b); // true (same object)
System.out.println(a == c); // false (c was new'd)
System.out.println(a == d); // true (interned into the pool)
// always compare content with equals
System.out.println(a.equals(c)); // true
}
}StringBuilder: Essential for Heavy Concatenation
Use cases: concatenating strings in a loop, building CSV / SQL / log lines. String's + creates a new object every time; using + in a loop is an O(n²) performance disaster. StringBuilder is a mutable internal buffer with a single final toString() — the gap can reach hundreds of times. StringBuffer is the thread-safe version of StringBuilder (with synchronized), rarely used day to day.
// Builder.java
public class Builder {
public static void main(String[] args) {
// ❌ bad example: + in a loop
// String s = "";
// for (int i = 0; i < 100_000; i++) s += i; // extremely slow
// ✅ StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) {
sb.append(i).append(",");
}
if (sb.length() > 0) sb.deleteCharAt(sb.length() - 1);
System.out.println(sb); // 0,1,2,3,4
// fluent API
String json = new StringBuilder()
.append("{\"name\":\"").append("Alice").append("\",")
.append("\"age\":").append(30).append("}")
.toString();
System.out.println(json);
}
}Text Blocks: Multi-line Strings (Java 15+)
Use cases: embedded SQL, JSON, HTML, SQL templates, error messages — previously you wrote a pile of \n and escaped quotes; now use a triple-quoted block. The compiler auto-strips indentation to the leftmost-aligned position.
// TextBlock.java
public class TextBlock {
public static void main(String[] args) {
String sql = """
SELECT id, name, email
FROM users
WHERE status = 'active'
AND created_at > ?
ORDER BY id
""";
System.out.println(sql);
String json = """
{
"name": "Alice",
"age": 30,
"tags": ["java", "go"]
}
""";
System.out.println(json);
// \<newline> line continuation: joins into a single line
String long1 = """
this is a very \
long single line
""";
System.out.println(long1);
}
}String.format / formatted
Use cases: building strings with placeholders — logs, error messages, user panels. printf-style %s %d %.2f, etc. Java 15+ added the instance method "...".formatted(args) for better readability.
// FormatDemo.java
public class FormatDemo {
public static void main(String[] args) {
String name = "Alice";
int age = 30;
double score = 87.5;
// classic: String.format
String s1 = String.format("%s is %d (score=%.2f)", name, age, score);
System.out.println(s1);
// Java 15+: instance method
String s2 = "%s is %d (score=%.2f)".formatted(name, age, score);
System.out.println(s2);
// width alignment, zero-padding
System.out.println(String.format("%-10s|%5d|%08d", "id", 42, 7));
// id | 42|00000007
}
}String.join and split
join glues collection elements with a separator, common for CSV, SQL IN lists, log formatting. split divides by a regex. Note: split's argument is a regex — to split on . write "\\.".
// JoinSplit.java
import java.util.List;
public class JoinSplit {
public static void main(String[] args) {
List<String> tags = List.of("java", "go", "rust");
String csv = String.join(", ", tags);
System.out.println(csv); // java, go, rust
// build a SQL IN list (PreparedStatement placeholders are actually safer)
String inList = String.join(",", tags);
String sql = "SELECT * FROM lang WHERE name IN (" + inList + ")";
System.out.println(sql);
// split: by regex
String line = "a, b, c , d";
String[] parts = line.split("\\s*,\\s*"); // any whitespace + comma + any whitespace
for (String p : parts) System.out.println("[" + p + "]");
// split on a period: needs escaping
String[] segs = "www.example.com".split("\\.");
for (String s : segs) System.out.println(s);
}
}Common Methods Cheat Sheet
// StringApi.java
public class StringApi {
public static void main(String[] args) {
String s = " Hello, Java World! ";
// length / index access
System.out.println(s.length());
System.out.println(s.charAt(2));
// case, whitespace
System.out.println(s.trim()); // trim leading/trailing ASCII whitespace
System.out.println(s.strip()); // trim leading/trailing Unicode whitespace (Java 11+, recommended)
System.out.println(s.toLowerCase());
System.out.println(s.toUpperCase());
// substring and search
System.out.println(s.substring(2, 7)); // Hello
System.out.println(s.indexOf("Java"));
System.out.println(s.contains("World"));
System.out.println(s.startsWith(" Hello"));
System.out.println(s.endsWith("! "));
// replace
System.out.println(s.replace("World", "Universe"));
System.out.println(s.replaceAll("\\s+", "_")); // regex replace
// emptiness check
System.out.println("".isEmpty()); // true
System.out.println(" ".isBlank()); // true (Java 11+)
// repeat (Java 11+)
System.out.println("=".repeat(10));
}
}Strings and Bytes (Encoding)
Use cases: network send/receive, writing files, Base64 encoding, crypto hashing. String <-> byte[] conversion **must** explicitly specify a charset (prefer UTF-8); otherwise it uses the platform default — which behaves differently across OSes and is a classic source of garbled text.
// Bytes.java
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
public class Bytes {
public static void main(String[] args) {
String s = "你好 Java";
// String -> byte[]
byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
byte[] gbk = s.getBytes(java.nio.charset.Charset.forName("GBK"));
System.out.println("utf8 bytes = " + utf8.length); // 11
System.out.println("gbk bytes = " + gbk.length); // 9
// byte[] -> String
String back = new String(utf8, StandardCharsets.UTF_8);
System.out.println(back);
// view as hex
StringBuilder hex = new StringBuilder();
for (byte b : utf8) hex.append(String.format("%02x ", b));
System.out.println(hex);
}
}