String 算是java开发中用到最多的一个对象了吧。其中的码点和代码单元的概念你听过吗,下面简单的介绍一下吧
如果不知道的话,你先看一下下面的代码输出的字符串长度是多少?
System.out.println("a🥧c".length());
下面就介绍以下码点和代码单元的慨念吧
码点(Code Point)是Unicode字符集中每个字符的唯一标识符,它用一个整数值来表示。在Java中,一个码点对应一个int类型的值,可以通过codePointAt()
方法获取字符串中指定位置的码点(就我们视觉上看到的一个字符
)。
代码单元(Code Unit)是在内存中存储和处理字符串时使用的基本单位。在Java中,使用UTF-16编码方案将Unicode字符编码为代码单元。UTF-16使用16位无符号整数(即char类型)来表示一个代码单元,对于表示较大的码点,需要使用多个代码单元进行编码。(java的char类型就是代码单元呢
)
在大多数情况下,一个代码单元就可以表示一个Unicode字符,此时一个代码单元就等于一个码点。但是对于一些辅助字符(Surrogate Character),一个码点需要使用两个代码单元来表示。这是因为Unicode字符集中的一些字符编码超过了16位的范围,需要使用代理对(Surrogate Pair)来进行编码。
以下是一些处理码点和代码单元的方法:
length()
方法返回字符串中代码单元的数量。
String str = "a🥧c";
int codeUnits = str.length(); // codeUnits = 4
codePointCount(int beginIndex, int endIndex)
方法返回指定范围内的码点数量。
String str = "a🥧c";
int codePoints = str.codePoints().count(); // codePoints = 3
charAt(int index)
方法返回指定位置的代码单元。
String str = "a🥧c";
char ch = str.charAt(1); // ch = '?'
codePointAt(int index)
方法返回指定位置的码点。
String str = "a🥧c";
int codePoint = str.codePointAt(1); // codePoint = 129383
看到这儿我们在平时遍历字符串时候,其实我们意图是遍历码点,只是平时开发中很少遇到两个单码单元的码点就基本上不会出问题。因此我们以后在处理字符串时,特别是在涉及到索引、截取和遍历操作时,应当考虑码点和代码单元之间的关系,以避免出现问题。
比如在我们不清楚码点和代码单元的关系之前,要提取 “a🥧c” 中间这个字符,我们可能直接 str.charAt(1) 了,这时候程序就跑远了,嘻嘻嘻嘻。。。。。。