一个字符的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时,就会以两个单元(四个字符)保存。

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。

/**
 * 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 @ 2020-01-14 16:57  Ninon  阅读(709)  评论(0编辑  收藏  举报