Language Fundamentals
Strings & Text
equals, never ==; build repeatedly-modified text with StringBuilder; and treat indexes as opaque because one visible character may span multiple chars.Stringis immutable — every "modification" returns a new string- Compare content with
equals/equalsIgnoreCase;==compares references - Loop concatenation is O(n²) — use
StringBuilder(EJ Item 63) length()counts UTF-16 code units, not visible characters — emoji count as 2+- Text blocks (
""") hold multi-line literals without escape noise - The compiler interns string literals: identical literals share one pooled instance
Immutability makes strings safe to share, cache, and use as map keys — the compiler exploits it by interning literals, so "Java" == "Java" happens to be true. But strings computed at runtime are separate objects, which is why == on strings is a classic bug.
The essential API
| Method | What it does |
|---|---|
substring(begin, end) | Extract [begin, end) — end is exclusive, length is end - begin |
indexOf / lastIndexOf | Position of a substring, −1 if absent |
contains, startsWith, endsWith | Containment tests |
strip() | Remove leading/trailing whitespace (Unicode-aware trim) |
toUpperCase() / toLowerCase() | Case conversion (locale-sensitive overloads exist) |
replace(old, new) | Replace all occurrences (plain text, no regex) |
split(regex) | Split into an array — the argument is a regex |
join(delim, parts...) | Static: join pieces with a delimiter |
repeat(n) | Repeat the string n times |
isEmpty() / isBlank() | Zero length / only whitespace |
formatted(args) / String.format | printf-style formatting |
chars() / codePoints() | Stream over code units / code points |
Building strings efficiently
For joining with separators, skip the manual loop entirely: String.join(", ", list) or list.stream().collect(Collectors.joining(", ", "[", "]")) (see Collectors).
Unicode reality
A char is a UTF-16 code unit. Characters outside the Basic Multilingual Plane — emoji, many CJK ideographs — occupy two chars (a surrogate pair), and human-perceived characters (grapheme clusters, like flag emoji) can span several code points. So "Ciao 🇮🇹".length() is 9. Use codePoints() to iterate real code points, and treat indexOf results as opaque positions. Internally the JVM stores Latin-1-only strings compactly as bytes (compact strings) — an invisible optimization.
String query = """
SELECT id, name
FROM users
WHERE active = true
""";
// Incidental indentation is stripped; no \n escapes needed. See the Text Blocks topic.