详解Character中的相关code-point方法

本文深入探讨Java中Unicode与Code-point的关系,解析Character类中关键code-point方法,包括toCodePoint、codePointCount等,阐述双位字符处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缘由

在java中有许多针对code-point的相关方法,由于工作需要,对部分常用的code-point方法进行记录下。

Unicode和Code-point的关系

“一个普通字符是一位,一个emoji表情是两位。Mysql应该用utf8mb4存储emoji,而不应该用utf8”这是大多数人真正意义上去了解到unicode的开端,关于unicode的一些基础知识在这里就不普及了。为了方便,下面的特殊unicode的展示都用emoji作为示例(毕竟这是大多数人所认知的双位字符)。

下面有一段代码

代码块1
String ch = "a";
System.out.println(ch.length());

很显然,输出的结果是1,因为a是一位;又有一段代码

代码块2
String emoji = "😠";
System.out.println(emoji.length());

这里的输出是2,但其实,这个emoji表情对于code-point来说的话其实是一个(应该用codePointCount来统计,后面API会说)。

那么现在有一个问题,有时候我们需要循环处理字符串中的内容,如果遇到这种情况会怎样?来看一段代码

代码块3
String ch = "abcd";
for (int i = 0; i < ch.length(); i++) {
    System.out.println(ch.charAt(i));
}

很显然,会分别打印出来a、b、c、d,那如果打印我们代码块2中的emoji时会发生什么事情,来看下代码

代码块4
String emoji = "😠";
for (int i = 0; i < emoji.length(); i++) {
    System.out.println(emoji.charAt(i));
}

不看答案,想一下会打印出什么。
自己去试一下的话会发现,打印出了两行问号,并不是一些人所认定的两行unicode代码(这个emoji的实际代码是\uD83D\uDE20)。
这样的情况对于我们去遍历一个字符串是不友好的。

API

Charatcer.toCodePoint

toCodePoint方法是将一个unicode的高位和低位进行结合后拼接输出,例如😠对应的unicode的是\uD83D\uDE20,可以调用codePoint对其进行拼接。

System.out.println( Character.toCodePoint('\uD83D','\uDE20'));

打印结果是128544,对应这个unicode字符。

Character.isValidCodePoint

isValidCodePoint用于判断当前输入是否是一个标准的codepoint,判断的标准和unicode的定义保持一致,是否位于0x000000~0X10FFFF之间

Character.codePointCount

计算数组中的codepoint数量,正如上方代码块2下方的解释一样,一个emoji应当算一个,而“你😠好”的codepoint的数量应当是3而不是4。

Character.isHighSurrogate\Character.isLowSurrogate

isHighSurrogate和isLowSurrogate是用于判断高位和地位的方法,例如😠对应的unicode的是\uD83D\uDE20,我们分别看下。

代码块5
System.out.println( Character.isHighSurrogate('\uD83D'));
System.out.println( Character.isHighSurrogate('\uDE20'));
System.out.println( Character.isLowSurrogate('\uD83D'));
System.out.println( Character.isLowSurrogate('\uDE20'));

结果分别是true\false\false\true,很显然,\uD83D是高位,\uDE20是低位。注意,如果是单字符,非双字节unicode,无论是isHighSurrogate还是isLowSurrogate都将返回false。

Character.codePointAt

codePointAt方法有多个实现,但终归是返回每一个codepoint的unicode代码,以刚刚代码块4进行举例.

代码块6
char[] emoji = "ab😠cd".toCharArray();
System.out.println(Character.codePointAt(emoji, 1));
System.out.println(Character.codePointAt(emoji, 2));
System.out.println(Character.codePointAt(emoji, 3));

这个地方打印出来的是结果如下。

98
128544
56864

注意,代码块6的打印结果中,第2行是结合了两个unicode得出来的结果,而第三方只是这个unicode的低位。

Character.codePointBefore

codePointBefore和codePointAt逻辑一样,但是在判断时不是当前的index,而是index之前的结果,例如传入的index是2,则查询的范围是0-1,注意,此处也会进行高低位的判断。

Character.highSurrogate\Character.lowSurrogate

highSurrogate和lowSurrogate是分别打印出一个双位unicode的高位和低位的数字结果,例如:

System.out.println( Character.toCodePoint(Character.highSurrogate(128544),Character.lowSurrogate(128544)));

打印结果自然是128544,还原了高位和低位

Character.isSurrogate

isSurrogate用大白话说,就是判断是否是合理的双位字符,合理的UTF-16字符最小是\u005CuD800例如如下代码:

代码块7
char[] emoji = "😠".toCharArray();
System.out.println( Character.isSurrogate(emoji[0]));
System.out.println( Character.isSurrogate(emoji[1]));
System.out.println( Character.isSurrogate('a'));

结果自然前两行是true,最后一行是false。

Character.isSurrogatePair

isSurrogatePair是用于判断两个字符是否是双位字符的一对(高位+低位),例如如下代码

代码块8
char[] emoji = "😠".toCharArray();
System.out.println( Character.isSurrogatePair(emoji[0],emoji[1]));
System.out.println( Character.isSurrogatePair(emoji[0],emoji[0]));

第一行的结果是true,第二行的结果是false,很显然。

Character.isSupplementaryCodePoint

isSupplementaryCodePoint的作用是判断是否是一个双位字符,和isSurrogate的区别是,isSupplementaryCodePoint只要是两位就是对的,而isSurrogate必须是合理的UTF-16字符。

Character.offsetByCodePoints

方法有两种实现,第一种是在一个字符串中,输入index和offset,求以codepoint角度下[index,index+offset]区间的最后一个codepoint后的对于array的索引,例如:

代码块9
System.out.println( Character.offsetByCodePoints("ab😠cd",1,3));
System.out.println( Character.offsetByCodePoints("abcde",1,3));

结果是5,4
"ab😠cd"的[1,4]范围内其实指的就是"b😠c"的最后一位"c"后的的array的index,则是5。

Character.isBmpCodePoint

这里涉及到一个概念,Bmp指的是Basic Multilingual Plane,如下的概念来自于百度百科

基本多文种平面,BMP(Basic Multilingual Plane),或称第零平面(Plane 0),是Unicode中的一个编码区段。编码从U+0000至U+FFFF。 Unicode 基本多文种平面的示意图。每个写着数字的格子代表256个码点。

其实就是判断输入字符是否在U+0000至U+FFFF范围内。

总结

总结了一下常用的Character中的常用对于unicode和surrogate的方法,对于codepoint也做了部分的解释,需要注意的地方是,有些API需要输入的是unicode的int值,而有些需要输入char,还有就是要深入理解"双位"字符的真正含义,BMP和UTF-16的区别。

### Java `Character.getNumericValue` 方法详解 #### 方法概述 `Character.getNumericValue()` 是 Java 中的一个静态方法,用于获取指定字符的 Unicode 数值。此方法可以接受两种参数形式:单个字符 (`char`) 或者 Unicode 编码点 (`int`)。 - 对于字符 `'0'-'9'`, `'A'-'F'`, 和 `'a'-'f'`,该函数会返回相应的十进制数值。 - 如果输入的是其他类型的字符,则依据其是否能被解释成有效的数字来决定返回值[^1]。 #### 方法签名 存在两个重载版本的方法: ```java public static int getNumericValue(char ch) ``` 以及 ```java public static int getNumericValue(int codePoint) ``` 这两个方法都接收一个待解析为数值的字符或者编码点作为参数,并尝试将其映射到一个整型数值上。 #### 参数描述 - **ch**: 要转换的目标字符。 - **codePoint**: 表示目标字符的Unicode编码点。 #### 返回结果解读 根据传入的不同类型字符,会有不同的返回情况: - 当给定字符确实对应着某个正整数时,将会得到这个正整数; - 若无法识别为有效数字(比如字母),则统一返回 `-1`; - 特殊情况下如果遇到罗马数字等特殊符号,可能会有额外定义范围内的负数返回,但通常不会低于 `-2`。 #### 实际应用案例 下面给出一段简单的代码片段展示如何利用 `getNumericValue` 来处理字符串中的数字字符: ```java // 定义测试字符变量 char digitChar = '7'; char nonDigitChar = 'g'; // 获取并打印字符对应的数值 System.out.println(Character.getNumericValue(digitChar)); // 输出 7 System.out.println(Character.getNumericValue(nonDigitChar));// 输出 -1 ``` 上述例子中可以看到,对于合法的阿拉伯数字字符可以直接获得预期的结果;而对于非数字字符如英文字母,则按照规定返回了错误指示符 `-1`[^3]。 #### 注意事项 值得注意的一点是,在某些特定场景下即使看起来像是数字但实际上并不属于标准意义上的 “数字”,也可能导致意外的行为。因此建议开发者们在实际项目里谨慎选用本API,并充分考虑边界条件下的表现[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值