プログラミングと開発

Java Unicode

Java strings use UTF-16 internally. char is 16-bit (only BMP). For supplementary characters, use codePointAt() and Character.toChars(). Java's \uXXXX escapes process at compile time.

What is Java Unicode Handling?

Java's approach to Unicode reflects the historical evolution of the Unicode Standard. Java was designed in the mid-1990s when Unicode was a 16-bit encoding, and this assumption was baked into the language's char type and String class. When Unicode later expanded to 21 bits to accommodate scripts like Egyptian Hieroglyphs and emoji, Java had to retrofit support for code points beyond U+FFFF — the supplementary characters.

The char Type: 16-bit BMP Only

Java's char is a 16-bit unsigned integer representing a UTF-16 code unit, not a full Unicode code point. This means char can represent only characters in the Basic Multilingual Plane (U+0000 to U+FFFF). Characters outside this range — everything from U+10000 onward — require two char values called a surrogate pair.

char c = '\u0041';  // 'A' — works fine, BMP character
// char cannot hold U+1F600 (😀) — it requires a surrogate pair

String as UTF-16

Java's String class stores its content as a UTF-16 sequence. For most Western text this is transparent, but supplementary characters produce a String where the visual character count differs from length():

String emoji = "😀";          // U+1F600 GRINNING FACE
emoji.length();               // 2 — two UTF-16 code units (surrogate pair)
emoji.codePointCount(0, emoji.length());  // 1 — one Unicode code point

codePointAt() vs charAt()

The distinction between code-unit-based and code-point-based iteration is the central Java Unicode challenge:

String s = "A😀B";

// charAt() — returns UTF-16 code units
s.charAt(0);   // 'A'
s.charAt(1);   // '\uD83D' — high surrogate, NOT a printable character
s.charAt(2);   // '\uDE00' — low surrogate

// codePointAt() — returns full Unicode code points
s.codePointAt(0);  // 65 (A)
s.codePointAt(1);  // 128512 (😀, U+1F600)
s.codePointAt(3);  // 66 (B)

For correct supplementary-character-aware iteration, use String.codePoints() in Java 8+:

s.codePoints().forEach(cp ->
    System.out.println(new String(Character.toChars(cp))));

The Character Class

Character provides static utility methods for Unicode properties. Since Java 5, many methods have overloaded versions that accept int code points (not just char):

Character.isLetter('A');                   // true
Character.isLetter(0x1F600);               // false (emoji, not a letter)
Character.getType('A');                    // Character.UPPERCASE_LETTER
Character.toUpperCase(0x0073);             // 0x0053 ('S')
Character.isSupplementaryCodePoint(0x1F600); // true

Pattern Matching and Unicode

Regular expressions in Java require the Pattern.UNICODE_CHARACTER_CLASS flag to make \w, \d, \s match Unicode categories rather than just ASCII:

Pattern p = Pattern.compile("\\w+", Pattern.UNICODE_CHARACTER_CLASS);
p.matcher("Héllo").matches();  // true — accented letter is a word char

Quick Facts

Feature Detail
char size 16 bits (BMP only, U+0000–U+FFFF)
String encoding UTF-16 internally
Supplementary chars Surrogate pairs (two char values)
Code point API codePointAt(), codePoints(), offsetByCodePoints()
Character utility isLetter(), getType(), toUpperCase() (int overloads)
Regex Unicode flag Pattern.UNICODE_CHARACTER_CLASS
Normalization java.text.Normalizer (NFC, NFD, NFKC, NFKD)
Collation java.text.Collator, java.text.RuleBasedCollator

関連用語

プログラミングと開発 のその他の用語

Python Unicode

Python 3 uses Unicode strings by default (str = UTF-8 internally via …

Rust Unicode

Rust strings (str/String) are guaranteed valid UTF-8. char type represents a Unicode …

Unicode エスケープシーケンス

ソースコードでUnicode文字を表す構文。言語によって異なります:\u2713(Python/Java/JS)・\u{2713}(JS/Ruby/Rust)・\U00012345(Python/C)。

Unicode 正規表現

Unicodeプロパティを使う正規表現パターン:\p{L}(任意の文字)・\p{Script=Greek}(ギリシャ語スクリプト)・\p{Emoji}。言語や正規表現エンジンによってサポートが異なります。

エンコーディング / デコーディング

エンコーディングは文字をバイトに変換し(str.encode('utf-8'))、デコーディングはバイトを文字に変換します(bytes.decode('utf-8'))。正しく行えば文字化けを防げます。

サロゲートペア

UTF-16で補助文字をエンコードするために使われる2つの16ビットコード単位(上位サロゲートU+D800〜U+DBFF + 下位サロゲートU+DC00〜U+DFFF)。😀 = D83D DE00。

ヌル文字

U+0000(NUL)。最初のUnicode/ASCII文字で、C/C++では文字列ターミネータとして使われます。セキュリティリスク:ヌルバイト挿入は脆弱なシステムで文字列を切り捨てる可能性があります。

不可視文字

目に見えるグリフを持たない文字:空白・ゼロ幅文字・制御文字・書式文字。スプーフィングやテキスト密輸などのセキュリティ問題を引き起こす可能性があります。

文字列

プログラミング言語における文字のシーケンス。内部表現はさまざまです:UTF-8(Go・Rust・新しいPython)・UTF-16(Java・JavaScript・C#)・UTF-32(Python)。

文字列長の曖昧さ

Unicodeの文字列の「長さ」は単位によって異なります:コード単位(JavaScript .length)・コードポイント(Python len())・書記素クラスター。👨‍👩‍👧‍👦 = 7コードポイント、1書記素。