public class Surrogate { public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ char c1 = '\u3042'; // HIRAGANA LETTER A, cp=12354 通常のひらがな char c2 = '\uD842'; // tuchi-yoshi (high), cp=134071 吉の下が長いやつ char c3 = '\uDFB7'; // tuchi-yoshi (low), cp=134071 char c4 = '\u30D5'; // katakana fu, cp=12501 カタカナの"フ" char c5 = '\u309A'; // handakuten, cp=12442 (半濁点゜の合成文字) char c6 = '\uD842'; // kuchi + shichi (high), cp=134047 ?? char c7 = '\uDF9F'; // kuchi + shichi (low), cp=134047 char c8 = '\uD840'; // ?? の上位ワード char c9 = '\uDC0b'; // ?? の下位ワード char c10 = '#'; // ただのアスキー文字 String s = new String(new char[] { c1, c2, c3, c4, c5, c6, c7, c8, c9, c10 }); System.out.println("str=" + s); // "あ??フ゜????#" という文字列(見た目は6文字) // char配列の長さ = 10文字 System.out.println("string len=" + s.length()); // コードポイントの長さ = 7文字 (半濁点も1と数えている。) System.out.println("codepoint count=" + s.codePointCount(0, s.length())); for (int idx = 0; idx < s.length();) { // codePointAtはchar配列のインデックスをとる。上位ワードを指定すると下位と合わせてcodepointとして返される。 // ただし、下位ワードのインデックスを指定した場合はサロゲートペアの下位ワードがそのまま返される。 int cp = s.codePointAt(idx); int len = Character.charCount(cp); // コードポイントがchar何個分か返す。これで下位ワードをスキップさせる。 String ch = new String(new int[] { cp }, 0, 1); System.out.println(ch + " -- codepoint=0x" + Integer.toHexString(cp) + " len=" + len); idx += len; } } }