java length()函数_美团面试官问我一个字符 String.length()是多少我说1面试官说滚

本文首发于微信公众号:程序员乔戈里

66683c6dbeb64550a2ffcae67731d8fc.png
e3eef0fc5b32260656f53ae6319eb329.png
4077c9039e5736f8efa35dbba0a6283d.png
93c6d45edaabfa4f6d33dfffa18711cd.png
3f063c960b53ef022657e0b839876454.png
1d4d1912339e3c039cf6f6fa47ce8850.png
9927f761daa3d0fbde7fd4e1429261ed.png
public class testT {    public static void main(String [] args){        String A = "hi你是乔戈里";        System.out.println(A.length());    }}

以上结果输出为7。

21d2846d48413691bacb2e944733db2f.png
fafaf5ed4ede23fdfb1b53f56d667de5.png
b3f1bb3e22f892acd45db6d9057090c7.gif
e6650bd53256e5b278d2f8483cbdd14e.png
c613f86cf6cb40557fcaffe746f1bbab.png
3c9f4317af34943c7a873e20d5714263.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;    }

接着使用google翻译对这段英文进行了翻译,得到了大体意思:返回字符串的长度,这一长度等于字符串中的 Unicode 代码单元的数目。

小萌:乔戈里,那这又是啥意思呢?乔哥:前几天我写的一篇文章:[https://mp.weixin.qq.com/s/Zn-BnMd2tohHPpvMhLFYxw](https://mp.weixin.qq.com/s/Zn-BnMd2tohHPpvMhLFYxw)里面对于Java的字符使用的编码有介绍:

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

  • 内码:char或String在内存里使用的编码方式。
  • 外码:除了内码都可以认为是“外码”。(包括class文件的编码)

而java内码:unicode(utf-16)中使用的是utf-16.所以上面的那句话再进一步解释就是:返回字符串的长度,这一长度等于字符串中的UTF-16的代码单元的数目。

465513134aefb5c6c9845f8b162b7504.png
e0d7bb9ddbef2097679b2fd53db65935.png

https://xiaogd.net/。UTF-X 中的数字 X 就是各自代码单元的位数。

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

你还记得你前几天被面试官说菜的时候学到的Unicode知识吗,在https://mp.weixin.qq.com/s/QjU9lSekpbaF7fugZbyzkg这里面提到,UTF-16编码一个字符对于U+0000-U+FFFF范围内的字符采用2字节进行编码,而对于字符的码点大于U+FFFF的字符采用四字节进行编码,前者是两字节也就是一个代码单元,后者一个字符是四字节也就是两个代码单元!

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

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

a6776d895c362f7bdeaf94f9b4c42fb4.png
dafe01aad233456ff4ab03639f3cd7f3.png
8ccd5d495d08a0f15e63585a6f57a70e.png
af3a63c51f524770c0090d6bc11dcc74.png

来看个例子!

public class testStringLength {    public static void main(String [] args){        String B = ""; // 这个就是那个音符字符,只不过由于当前的网页没支持这种编码,所以没显示。        String C = "?";// 这个就是音符字符的UTF-16编码        System.out.println(C);        System.out.println(B.length());        System.out.println(B.codePointCount(0,B.length()));           }}
87ea89b7b97a4ae404382fc222d09f1e.gif

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

76268f84fe1b8863674ce02cb529f529.png

几个问题:0.codePointCount是什么意思呢?1.之前不是说音符字符是“U+1D11E”,为什么UTF-16是"uD834uDD1E",这俩之间如何转换?2.前面说了UTF-16的代码单元,UTF-32和UTF-8的代码单元是多少呢?

b0f5b9712c20e65b9b42de8ba6667d9f.png

一个一个解答:

https://blog.csdn.net/u012425381/article/details/38760179

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

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

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

https://mp.weixin.qq.com/s/QjU9lSekpbaF7fugZbyzkg

878257f4f6337e97be78a025bf60e157.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 可以包含一个单元,二个单元,三个单元及四个单元,对应即是一,二,三及四字节。
f2cabd529950e2e31a4b74cb5c3afe47.png

参考

  • 表情包出自微博@黄小B
  • https://blog.csdn.net/u012425381/article/details/38760179
  • https://xiaogd.net/
  • https://tool.oschina.net/hexconvert
  • https://baike.baidu.com/item/Unicode/750500?fr=aladdin

本文首发于微信公众号:程序员乔戈里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值