Learning goals
Use String and related APIs safely: immutability, concatenation, comparison, searching, splitting, formatting, and StringBuilder for efficient mutation.
Strings are immutable
String s = "hello";
s.toUpperCase(); // returns new String "HELLO"
System.out.println(s); // still "hello"
Once created, a String’s character sequence does not change. “Modification” creates a new object. Immutability enables string interning, thread safety, and safe sharing.
Creating strings
String a = "hello"; // string pool (literal)
String b = new String("hello"); // heap object (usually avoid)
String c = String.valueOf(42); // "42"
Prefer literals when possible; new String("...") duplicates unnecessarily unless you need a fresh heap instance.
Concatenation
String msg = "Hello, " + name + "!";
Compiler may optimize with StringBuilder under the hood for simple + chains. In loops, build explicitly:
StringBuilder sb = new StringBuilder();
for (String word : words) {
sb.append(word).append(' ');
}
String result = sb.toString().trim();
Comparison
"abc".equals(other); // null-safe if literal first
Objects.equals(a, b); // null-safe both sides
"abc".equalsIgnoreCase("ABC");
"a".compareTo("b"); // negative if a < b lexicographically
Never use == for content unless you intentionally test interned identity.
Useful methods
String text = " Java 21 ";
text.length();
text.isEmpty(); // true if length 0
text.isBlank(); // JDK 11+: whitespace only
text.strip(); // trim Unicode-aware
text.toLowerCase();
text.startsWith("Java");
text.endsWith("21");
text.contains("21");
text.indexOf('a');
text.substring(2, 6); // [begin, end)
text.replace("21", "17");
Splitting and joining
String csv = "one,two,three";
String[] parts = csv.split(",");
String joined = String.join("-", parts); // one-two-three
Regex in split treats metacharacters specially: "a.b".split(".") splits every char—escape: split("\\.").
Text blocks (JDK 15+)
String json = """
{
"name": "Ada",
"role": "engineer"
}
""";
Trailing newline can be suppressed with \ on last line if needed.
Formatting
String formatted = String.format("Price: %.2f USD", 19.5);
// JDK 15+
String s = "Value: %s".formatted("x");
For locale-aware dates and numbers, use java.time formatters—not string hacks.
StringBuilder vs StringBuffer
| StringBuilder | StringBuffer | |
|---|---|---|
| Thread-safe | No | Yes (synchronized) |
| Speed | Faster | Slower |
| Typical use | Single-threaded building | Legacy shared mutation |
Almost always choose StringBuilder in application code.
Character encoding
Strings are UTF-16 internally. Bytes on the wire need charset:
byte[] utf8 = text.getBytes(StandardCharsets.UTF_8);
String back = new String(utf8, StandardCharsets.UTF_8);
Always specify StandardCharsets.UTF_8—never rely on platform default.
Common mistakes
==for equality — use.equals.- Heavy
+in loops — O(n²) copies; useStringBuilder. substringindices — end index exclusive; easy off-by-one.- Null caller:
name.equals("x")NPE ifnamenull — flip or useObjects.equals. - Splitting with regex metacharacters without escaping.
Practice checkpoint
-
Check if
emailends with@company.com(case-insensitive hint optional).- Answer:
email != null && email.toLowerCase().endsWith("@company.com")
- Answer:
-
Reverse words in
"hello world"without extra libraries.- Answer: Split on space, build from end with
StringBuilder.
- Answer: Split on space, build from end with
-
Why is
Stringimmutable?- Answer: Security (params, class names), thread safety, hash cache, pool sharing.
-
"abc".substring(1, 3)result?- Answer:
"bc"
- Answer:
Interview angles
- “String pool / intern?” — Literals deduplicated in pool;
intern()adds heap strings to pool—use sparingly (memory trade-off). - “String vs StringBuilder?” — Immutable vs mutable; builder for repeated modification.
- “How many objects?” —
new String("a") + new String("b")creates several intermediate objects; compiler may optimize constant expressions.