Skip to content

All tools (41)

JSON 6
Time & Date 4
Encoding & Decoding 4
Generators 3
Text & Data 4
Logs & Debugging 1
Config & Infra 3
Security & Hashing 4
Color & Design 5
Numbers & Bits 3
Web & Markup 4

Nothing leaves the cave.

Nothing you paste ever leaves your device. There is no server to send it to.

How you can check →
DevToolsCave

    This tool runs entirely in your browser. Nothing you paste is uploaded.

    How you can check →

    Java regex tester — java.util.regex rules for Java, Kotlin, Scala and Android

    Ships in: Java, Kotlin, Scala, Android

    Want to test your own pattern under Java (java.util.regex)? Open the regex tester with this flavor already selected.

    Open the regex tester — Java (java.util.regex) →

    java.util.regex is the engine underneath Pattern and Matcher in Java itself, and it is also what Kotlin, Scala and Android app code compile their regular expressions against — one engine, four names on the ecosystem, and one set of rules that diverges from JavaScript, Python and Go in ways that matter the first time a pattern crosses between them.

    The default-ASCII trap here is the most consequential one on this page, because Java's defaults point the opposite direction from Python and .NET. \d, \w, \s and \b are ASCII-only unless UNICODE_CHARACTER_CLASS is explicitly set on the Pattern — and almost nobody sets it. A validator written and tested in Python (Unicode-aware \d by default) will accept input that the same-looking pattern silently rejects in Java, and vice versa if a Java pattern gets ported to Python assuming ASCII-only behavior. This is measured directly against a real JDK, not assumed from documentation: Java's default genuinely is the ASCII-restrictive one.

    Lookbehind, by contrast, is one of the more permissive corners of java.util.regex — it is unbounded-width, not fixed-width and not merely bounded. (?<=a+)b and (?<=a*)b both compile and match correctly against long runs of repeated characters, putting Java in the same camp as .NET and JavaScript (ES2018+) rather than the fixed-width-only camp Python and PCRE2 enforce. An earlier draft of this project's own internal notes assumed Java required bounded-width lookbehind on the strength of older documentation; direct testing against a real JDK showed that assumption was wrong, which is exactly the kind of gap a browser-only tester using JavaScript's own RegExp under a "Java" label would never catch.

    java.util.regex is also stricter than most flavors about a literal { that doesn't form a valid quantifier. Where JavaScript's legacy Annex-B grammar and Python's re module both quietly treat a bare { as a literal character when it isn't part of {n,m}, Java throws a PatternSyntaxException instead — "Illegal repetition" — at compile time. A pattern that happens to work by accident in JavaScript or Python because of this leniency will fail loudly, not silently, the moment it's compiled under Java.

    Named groups use the (?<name>...) spelling, matching JavaScript, .NET and PCRE2 rather than Python's (?P<name>...) — and the matching backreference is \k<name>, again aligning with JavaScript and .NET rather than Python's (?P=name) or PCRE2's \g{name}. If you're maintaining the same pattern logic across a Java backend and a JavaScript frontend, named-group syntax is one of the few places you don't have to translate anything.

    Case-insensitive matching (CASE_INSENSITIVE, the i flag here) is ASCII-only by default too, exactly mirroring the \d/\w/\s split — you need UNICODE_CASE set alongside it to get Unicode-aware case folding, otherwise an accented letter's uppercase and lowercase forms won't be treated as equivalent. This is a second, independent instance of the same "Java defaults to ASCII, you have to opt in to Unicode" pattern that runs through the whole flavor.

    Free-spacing mode is available too, via the COMMENTS flag (the x letter here), and works the same way it does in PCRE2 and Python: unescaped whitespace inside the pattern is ignored and # starts a line comment, letting a multi-field extractor be laid out one token per line with an inline explanation rather than compressed onto one dense line. It's a plain compile-time Pattern flag, not inline pattern syntax, so it applies to the whole pattern uniformly rather than being scoped to part of it.

    One more Unicode-adjacent flag worth knowing about is CANON_EQ, which makes composed and decomposed forms of the same character compare equal — the single accented character é and the two-code-point sequence e + combining acute accent, which look identical on screen and are canonically the same character under Unicode, are treated as equal matches only when this flag is set. Without it, a pattern built from one form will silently fail to match text typed or normalized into the other, which is a real and recurring source of "this obviously matches, why doesn't it" bug reports whenever input comes from a source that doesn't normalize consistently — copy-pasted text from macOS versus a web form, in practice, being the most common pairing where this bites.

    Java (java.util.regex) quirks, at a glance

    The same facts this tool's engine implements and tests against — not a separate, unverified summary.

    • Lookbehind is unbounded — (?<=a+)b and (?<=a*)b both compile and match, unlike Python's fixed-width-only rule (measured directly, not assumed from docs).
    • \d, \w, \s and \b are ASCII-only unless UNICODE_CHARACTER_CLASS is set, which almost nobody sets — this is the most common Java/Python divergence.
    • An unescaped { that is not a valid quantifier is a PatternSyntaxException — unlike JavaScript's Annex-B grammar or Python, which both accept it as a literal.

    A worked example: Java (Pattern)

    Extracting a date like 2026-08-22^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$.

    Java (Pattern)
    Pattern.compile("^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$")

    \d, \w, \s and \b are ASCII-only here unless you also pass Pattern.UNICODE_CHARACTER_CLASS — almost nobody sets it, which is the most common Java/Python divergence.

    Frequently asked questions

    Does \d match Unicode digits in Java?
    No, not by default. \d, \w, \s and \b are ASCII-only in java.util.regex unless UNICODE_CHARACTER_CLASS is explicitly set on the Pattern — the opposite default from Python and .NET, both Unicode-aware out of the box.
    Is lookbehind bounded-width in Java?
    No — Java's lookbehind is unbounded-width, verified directly against a real JDK: (?<=a+)b compiles and matches correctly against long runs of repeated characters, putting Java alongside .NET and modern JavaScript rather than the fixed-width-only rule Python and PCRE2 enforce.
    Why does my pattern with a stray { fail to compile in Java?
    java.util.regex treats an unescaped { that doesn't form a valid {n,m} quantifier as a PatternSyntaxException ("Illegal repetition"), rather than silently reading it as a literal character the way JavaScript's legacy grammar and Python's re module both do.
    Does case-insensitive matching handle accented letters in Java?
    Only if UNICODE_CASE is set alongside CASE_INSENSITIVE. Without it, case folding is ASCII-only, so an accented letter's uppercase and lowercase forms are not treated as equivalent.