java 1个字符_Java一个字符的String.length()竟然不是1?

博客围绕Java中字符串长度展开,通过示例展示String.length()函数输出结果。介绍Java内码使用unicode(utf - 16),解释UTF - 16编码规则,如对不同范围字符的编码字节数。还解答了codePointCount含义、UTF - 16编码转换及UTF - 32、UTF - 8代码单元等问题。

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

65fe3c67faa2540143c7e6d8c27ee340.png

8c09de34c03dd4b6544c3bedb9fad1c6.png

3e5ab40e83707f20c929584cda7a7acb.png

4ffe7d450dce7e8fc698a1312192b6c8.png

cb55a4a777faee8326c057afde4a1270.png

1d7b07901ed4637eb231e7a1921a297a.png

fc762e92269b745b9313bd30dd47b721.png

public class testT {

public static void main(String [] args){

String A = "hi你是乔戈里";

System.out.println(A.length());

}

}

以上结果输出为7。

f7ac01c0214fd07173d09c9e75480f06.png

91f2c68b8449ffa42c6291db5dd16a45.png

f773012425359b7b4d4bcd27a01f24e7.png

6962cdfd8c78759d3159a41a46b6eafc.png

2c3b4a7815340bfe1b7829b74fe05bd6.png

18cae30465535ac1191e6aaf978dfc5d.png

小萌边说边在IDEA中的win环境下选中String.length()函数,使用ctrl+B快捷键进入到String.length()的定义。

/**

* Returns the length of this string.

* The length is equal to the number of Unicode

* code units in the string.

*

* @return the length of the sequence of characters represented by this

* object.

*/

public int length() {

return value.length;

}

接着使用

小萌:乔戈里,那这又是啥意思呢?

乔哥:前几天我写的一篇文章:面试官问你编码相关的面试题,把这篇甩给他就完事!里面对于Java的字符使用的编码有介绍:

Java中 有内码和外码这一区分简单来说

内码:char或String在内存里使用的编码方式。

外码:除了内码都可以认为是“外码”。(包括class文件的编码)

而java内码:unicode(utf-16)中使用的是utf-16.

所以上面的那句话再进一步解释就是:返回字符串的长度,这一长度等于字符串中的UTF-16的代码单元的数目。

c7abe650d93ad05c7539dc959f4e18e4.png

b06db3a9682fbd67a9710cd7f2038e44.png

UTF-16 的 16 指的就是最小为 16 位一个单元,也即两字节为一个单元,UTF-16 可以包含一个单元和两个单元,对应即是两个字节和四个字节。我们操作 UTF-16 时就是以它的一个单元为基本单位的。

你还记得你前几天被面试官说菜的时候学到的Unicode知识吗,在面试官让我讲讲Unicode,我讲了3秒说没了,面试官说你可真菜这里面提到,UTF-16编码一个字符对于U+0000-U+FFFF范围内的字符采用2字节进行编码,而对于字符的码点大于U+FFFF的字符采用四字节进行编码,前者是两字节也就是一个代码单元,后者一个字符是四字节也就是两个代码单元!

而上面我的例子中的那个字符的Unicode值就是“U+1D11E”,这个Unicode的值明显大于U+FFFF,所以对于这个字符UTF-16需要使用四个字节进行编码,也就是使用两个代码单元!

所以你才看到我的上面那个示例结果表示一个字符的String.length()长度是2!

64595a7a685a4333e778b3591a5cefb0.png

da7029331970e2de8a9d4215afffcd9e.png

aeb4a555068905f3a9067c24408b1538.png

021bdbe7621df9613007ff25efdc6f0f.png

来看个例子!

public class testStringLength {

public static void main(String [] args){

String B = "𝄞"; // 这个就是那个音符字符,只不过由于当前的网页没支持这种编码,所以没显示。

String C = "\uD834\uDD1E";// 这个就是音符字符的UTF-16编码

System.out.println(C);

System.out.println(B.length());

System.out.println(B.codePointCount(0,B.length()));

}

}

86b68ce0993e822304bc147f0588d181.png

可以看到通过codePointCount()函数得知这个音乐字符是一个字符!

d2a7ec3156acffb40cd934425ecacdf2.png

几个问题:

0.codePointCount是什么意思呢?

1.之前不是说音符字符是“U+1D11E”,为什么UTF-16是"\uD834\uDD1E",这俩之间如何转换?

2.前面说了UTF-16的代码单元,UTF-32和UTF-8的代码单元是多少呢?

94ece109504fdb3348046f4af328bb84.png

一个一个解答:

codePointCount其实就是代码点数的意思,也就是一个字符就对应一个代码点数。

比如刚才音符字符(没办法打出来),它的代码点是U+1D11E,但它的***单元是U+D834和U+DD1E,如果令字符串str = "\u1D11E",机器识别的不是音符字符,而是一个代码点”/u1D11“和字符”E“,所以会得到它的代码点数是2,代码单元数也是2。

但如果令字符str = "\uD834\uDD1E",那么机器会识别它是2个代码单元***,但是是1个代码点(那个音符字符),故而,length的结果是代码单元数量2,而codePointCount()的结果是代码点数量1.

e9b71502fbf48a22c327f5791aae3527.png

上图是对应的转换规则:

首先 U+1D11E-U+10000 = U+0D11E

接着将U+0D11E转换为二进制:0000 1101 0001 0001 1110,前10位是0000 1101 00 后10位是01 0001 1110

接着套用模板:110110yyyyyyyyyy 110111xxxxxxxxxx

U+0D11E的二进制依次从左到右填入进模板:110110 0000 1101 00 110111 01 0001 1110

然后将得到的二进制转换为16进制:d834dd1e,也就是你看到的utf-16编码了

第2个问题

同理,UTF-32 以 32 位一个单元,它只包含这一种单元就够了,它的一单元自然也就是四字节了。

UTF-8 的 8 指的就是最小为 8 位一个单元,也即一字节为一个单元,UTF-8 可以包含一个单元,二个单元,三个单元及四个单元,对应即是一,二,三及四字节。

f288ce2ad2956fb0cc687ac119bbbd0c.png

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值