Java字符串是一系列的Unicode字符序列,但是,它却常常被误认为是char序列。于是,我们经常这样来遍历字符串:

package testchar; public class TestChar2 { public static void main(String[]
args) { String s = "\u0041\u00DF\u6771\ud801\uDC00"; for(int i = 0; i <
s.length(); i++) { System.out.println(s.charAt(i)); } } }然后,得到了意料之外的结果:

A

ß



?

?


之所以会这样,是因为Unicode字符和Java的char类型不能等同起来。实际上,Java中的char类型能表示的字符只是Unicode字符的子集,因为char只有16位,也就是说,它只能表示65536(2的16次方)个字符,但实际的Unicode字符数超过这个数字。在Java中,用UTF-16编码char和String中的字符,一个字符对应的编码值被称为一个代码点。有的代码点用16位编码,被称为一个代码单元,像char表示的那些字符;有的代码点用32位编码,也就是用两个连续的代码单元编码,如上文中的\ud801\uDC00。其实,我们遍历一个字符串,遍历的是这个字符串中所有代码点,而

s.length()

返回的是字符串s中代码单元的个数。当i对应的代码单元只是一个32位代码点的一部分时,

s.charAt(i)

也就不能像我们希望的那样工作了。

下面给出了几种正确遍历一个字符串的方法:

package testchar; /** * 正确遍历String * * @author yuncong * */ public class
TestChar { public static void main(String[] args) { String s =
"\u0041\u00DF\u6771\ud801\uDC00"; // 获得字符串中代码点的数量 int cpCount =
s.codePointCount(0, s.length()); for (int i = 0; i < cpCount; i++) { int index
= s.offsetByCodePoints(0, i); int cp = s.codePointAt(index); if
(!Character.isSupplementaryCodePoint(cp)) { System.out.println((char) cp); }
else { System.out.println(cp); } } System.out.println("-------------------");
for (int i = 0; i < s.length(); i++) { int cp = s.codePointAt(i); if
(!Character.isSupplementaryCodePoint(cp)) { System.out.println((char) cp); }
else { System.out.println(cp); i++; } }
System.out.println("-------------------"); // 逆向遍历字符串 for(int i = s.length() -
1; i >= 0; i--) { int cp = 0; // 当i等于0的时候,只剩下一个代码单元,不可能是辅助字符 if (i == 0) { cp =
s.codePointAt(0); System.out.println((char)cp); } else { // 只有在i大于0的时候才可以退,并且
// 因为剩下的代码单元大于2,所以接下 // 来访问的两个代码单元可能表示辅助 // 字符; // 退一个代码单元 i--; cp =
s.codePointAt(i); if (Character.isSupplementaryCodePoint(cp)) {
System.out.println(cp); } else { // 如果cp不是辅助字符,就回到遍历的正常位置 i++; cp =
s.codePointAt(i); System.out.println((char)cp); } } } } }

(天坑啊,博客中不能出现Java中的辅助字符)

技术
©2019-2020 Toolsou All rights reserved,
王者荣耀背景故事整合痴心妄想随机森林篇 R语言实现用C++跟你聊聊“原型模式” (复制/拷贝构造函数)再见!经典版Edge!PYTHON入门期末复习汇总2021年1月程序员工资统计,平均14915元详解ubuntu14.04如何设置静态IP胡润:中国600万资产“富裕家庭”数量首次突破500万户苹果与日产对话暂停,Apple Car进展如何?