一个字符的String.length()为什么不一定等于1

参考文章:https://juejin.im/post/5e0e0bc66fb9a047eb2d335d?utm_source=gold_browser_extension

从文章中我们知道,java内码是是使用unicode(utf-16),而unicode的字符范围是U+0000-U+FFFF。

utf-16指的是16 位一个单元(一单元=两字节),当字符内容超出U+FFFF时,就会以两个单元(四个字符)保存。

1
2
3
4
5
6
public class testStringLength {
    public static void main(String[] args) {
        String B = "𝄞";
        System.out.println(B.length());//2
    }
}

这里B.length()输出2是因为字符(U+1D11E)号超出出U+FFFF,因此会拆成两个U+D834、U+DD1E来记录,而通过length源码我们知道他是通过unicode来判断长度的,所以才会输出2。

1
2
3
4
5
6
7
8
9
10
11
/**
 * Returns the length of this string.
 * The length is equal to the number of <a href="Character.html#unicode">Unicode
 * code units</a> in the string.
 *
 * @return  the length of the sequence of characters represented by this
 *          object.
 */
public int length() {
    return value.length;
}

那我们如何获取长度呢?文中是使用codePointCount

 

为了解决超出U+FFFF时的问题,Unicode制定了Surrogate(代理单元)这个概念,通过定义U+D800至U+DBFF為「High Surrogates」,U+DC00至U+DFFF為「Low Surrogates」,一共2048个。

那么在超出U+FFFF时,就拆分为两个单元定义(前者高代理,后者低代理),如果符合条件就识别为代理单元。

这里我们看到,使用isHighSurrogate判断U+D834高代理,isLowSurrogate判断U+DD1E低代理,同时满足即为代理单元,那就长度n直接-1,因此获取到我们需要的长度值1。

   

posted @   Ninon  阅读(725)  评论(0编辑  收藏  举报
编辑推荐:
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示