00 — Start here¶
Level: 101 · read this first
This library is for someone who can already write Java and has been surprised by text: a name that came back with ? in it, a comparison that failed on two strings that looked the same, a CSV whose first column stopped matching, a regex that worked in testing and not in Warsaw.
What it assumes¶
That you know Java syntax. That you have met Unicode as a word. Nothing else — the encoding background each page needs is on that page.
The four to read first¶
If you read nothing else, read these, in this order. They are the four that account for most real bugs:
- A
charis not a character — the 1995 decision everything else follows from. - Malformed input has two policies — why
new String(bytes)destroys evidence. - Case is locale-sensitive — how
toLowerCase()breaks a feature in Turkey. splithas sharp edges — the one you will hit this week.
How to read a page¶
Each has the same shape: a one-line summary, the idea in prose, a measured output block from a program in that page's examples/ folder, and what to do instead. The output blocks are generated, never typed — if a page shows you a number, a real JVM produced it.
Java's text scorecard, honestly¶
A summary of the whole library, so you know what you are walking into:
Genuinely good
- Unicode support has been there since day one, at a time when C had nothing and Python 2 was a decade from fixing it.
Stringis immutable and thread-safe, which removes an entire category of bug that C and C++ still have.- Since Java 18, the default charset is UTF-8 everywhere — the single biggest fix in the language's text history.
Files.readStringis strict about malformed input,NormalizerandCollatorandBreakIteratorare all in the JDK, and the ICU-derived locale data is excellent.- Compact Strings (Java 9+) store Latin-1 text at one byte per character, so the UTF-16 model does not cost double the memory it used to.
- Since Java 9 the
+operator compiles to aninvokedynamicthat builds a tailored, often single-allocation concatenation at link time — so straight-line concatenation is faster than a hand-writtenStringBuilder. See Concatenation and performance.
Genuinely bad
charis 16 bits and named as if it were a character.length(),charAt(),substring()all work in storage units and none of them says so.- The most reachable API for decoding bytes is the one that silently replaces corruption.
- Six or more
String/Formatmethods depend on an ambient locale, and the locale-taking overload is always the longer one. splittakes a regex and discards trailing empty fields.\uescapes are processed before lexing, which is a wart with a security face.- Accumulating with
+=in a loop is quadratic, and nothing in the language or the JIT will save you from it.
The pattern: almost every flaw is a default chosen for compatibility, with a correct alternative sitting right next to it, one argument longer. Java rarely makes the right thing impossible. It makes the wrong thing shorter.