<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你說(shuō),一個(gè)Java字符串到底有多少個(gè)字符?

          共 4422字,需瀏覽 9分鐘

           ·

          2020-08-09 06:56

          點(diǎn)擊上方藍(lán)色“小哈學(xué)Java”,選擇“設(shè)為星標(biāo)

          回復(fù)“資源”獲取獨(dú)家整理的學(xué)習(xí)資料!


          依照J(rèn)ava的文檔, Java中的字符內(nèi)部是以UTF-16編碼方式表示的,最小值是?\u0000?(0),最大值是\uffff(65535), 也就是一個(gè)字符以2個(gè)字節(jié)來(lái)表示,難道Java最多只能表示 65535個(gè)字符?

          char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).

          from?The Java? Tutorials

          首先,讓我們先看個(gè)例子:

          public?class?Main?{
          ????public?static?void?main(String[]?args)?{
          ????????//?中文常見(jiàn)字
          ????????String?s?=?"你好";
          ????????System.out.println("1.?string?length?="?+?s.length());
          ????????System.out.println("1.?string?bytes?length?="?+?s.getBytes().length);
          ????????System.out.println("1.?string?char?length?="?+?s.toCharArray().length);
          ????????System.out.println();
          ????????//?emojis
          ????????s?=?"??";
          ????????System.out.println("2.?string?length?="?+?s.length());
          ????????System.out.println("2.?string?bytes?length?="?+?s.getBytes().length);
          ????????System.out.println("2.?string?char?length?="?+?s.toCharArray().length);
          ????????System.out.println();
          ????????//?中文生僻字
          ????????s?=?"?妹";
          ????????System.out.println("3.?string?length?="?+?s.length());
          ????????System.out.println("3.?string?bytes?length?="?+?s.getBytes().length);
          ????????System.out.println("3.?string?char?length?="?+?s.toCharArray().length);
          ????????System.out.println();
          ????}
          }

          運(yùn)行這個(gè)程序,你覺(jué)得輸出結(jié)果是什么?

          輸出結(jié)果:

          1.?string?length?=2
          1.?string?bytes?length?=6
          1.?string?char?length?=2
          2.?string?length?=4
          2.?string?bytes?length?=8
          2.?string?char?length?=4
          3.?string?length?=3
          3.?string?bytes?length?=7
          3.?string?char?length?=3

          我們知道,?String.getBytes()如果不指定編碼格式,Java會(huì)使用操作系統(tǒng)的編碼格式得到字節(jié)數(shù)組,在我的MacOS中,默認(rèn)使用UTF-8作為字符編碼(locale命令可以查看操作系統(tǒng)的編碼),所以在我的機(jī)器運(yùn)行,String.getBytes()會(huì)返回UTF-8編碼的字節(jié)數(shù)組。

          String.length返回Unicode code units的長(zhǎng)度。

          String.toCharArray返回字符數(shù)組。

          我們?cè)O(shè)置的字符串都是兩個(gè)unicode字符,輸出結(jié)果:

          • 普通的中文字:字符串的長(zhǎng)度是2,每個(gè)中文字按UTF-8編碼是三個(gè)字節(jié),字符數(shù)組的長(zhǎng)度看起來(lái)也沒(méi)問(wèn)題
          • emojis字符:我們?cè)O(shè)置了兩個(gè)emojis字符,男女頭像。結(jié)果字符串的長(zhǎng)度是4,?UTF-8編碼8個(gè)字節(jié),字符數(shù)組的長(zhǎng)度是4
          • 生僻的中文字:我們?cè)O(shè)置了兩個(gè)中文字,其中一個(gè)是生僻的中文字。結(jié)果字符串的長(zhǎng)度是3,?UTF-8編碼7個(gè)字節(jié),字符數(shù)組的長(zhǎng)度是3

          看起來(lái)字符串的字符數(shù)和我們預(yù)期的有點(diǎn)不一樣,我們的字符串只有兩個(gè)unicode字符, 可是輸出結(jié)果有時(shí)候是2,有時(shí)候是3, 有時(shí)候是4,為什么呢?這還得從Java的歷史說(shuō)起。

          Java最初設(shè)計(jì)的Charactor用兩個(gè)字節(jié)來(lái)表示unicode字符,這沒(méi)有問(wèn)題, 因?yàn)樽畛鮱nicode中的字符還比較少, Java 1.1之前采用Unicode version 1.1.5, JDK 1.1中支持Unicode 2.0, JDK 1.1.7支持Unicode 2.1, Java SE 1.4 支持?Unicode 3.0, Java SE 5.0開(kāi)始支持Unicode 4.0

          直到Unicode 3.0, Java用兩個(gè)字節(jié)來(lái)表示unicode字符還沒(méi)有問(wèn)題,因?yàn)?code style="font-size: 14px;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(30, 107, 184);background-color: rgba(27, 31, 35, 0.05);font-family: 'Operator Mono', Consolas, Monaco, Menlo, monospace;word-break: break-all;">Unicode 3.0最多49,259個(gè)字符, 兩個(gè)字節(jié)可以表示65,535個(gè)字符,還足夠容的下所有的uicode3.0字符。

          但是Unicode 4.0(事實(shí)上自Unicode 3.1), 字符集進(jìn)行很大的擴(kuò)充,已經(jīng)達(dá)到了96,447個(gè)字符,Unicode 11.0已經(jīng)包含137,374個(gè)字符。

          在Unicode中,為每一個(gè)字符對(duì)應(yīng)一個(gè)編碼點(diǎn)(一個(gè)整數(shù)),用 U+緊跟著十六進(jìn)制數(shù)表示。所有字符按照使用上的頻繁度劃分為 17 個(gè)平面(編號(hào)為 0-16),即基本的多語(yǔ)言平面和增補(bǔ)平面。基本的多語(yǔ)言平面(英文為 Basic Multilingual Plane,簡(jiǎn)稱 BMP)又稱平面 0,收集了使用最廣泛的字符。

          這樣一來(lái),Java的Charactor的兩個(gè)字節(jié)的設(shè)計(jì),已經(jīng)不足以容納所有的Unicode 4的字符, 所以可能需要4個(gè)字節(jié)才能表示擴(kuò)展字符,所以現(xiàn)在的Charactor代表的已經(jīng)不再是一個(gè)字符?(代碼點(diǎn) code point), 而是一個(gè)代碼單元(code unit)。

          • Code Point: 代碼點(diǎn),一個(gè)字符的數(shù)字表示。一個(gè)字符集一般可以用一張或多張由多個(gè)行和多個(gè)列所構(gòu)成的二維表來(lái)表示。二維表中行與列交叉的點(diǎn)稱之為代碼點(diǎn),每個(gè)碼點(diǎn)分配一個(gè)唯一的編號(hào)數(shù)字,稱之為碼點(diǎn)值或碼點(diǎn)編號(hào),除開(kāi)某些特殊區(qū)域(比如代理區(qū)、專用區(qū))的非字符代碼點(diǎn)和保留代碼點(diǎn),每個(gè)代碼點(diǎn)唯一對(duì)應(yīng)于一個(gè)字符。從U+0000?到?U+10FFFF

          • Code Unit:代碼單元,是指一個(gè)已編碼的文本中具有最短的比特組合的單元。對(duì)于 UTF-8 來(lái)說(shuō),代碼單元是 8 比特長(zhǎng);對(duì)于 UTF-16 來(lái)說(shuō),代碼單元是 16 比特長(zhǎng)。換一種說(shuō)法就是 UTF-8 的是以一個(gè)字節(jié)為最小單位的,UTF-16 是以兩個(gè)字節(jié)為最小單位的。

          Java的字符在內(nèi)部以UTF-16編碼方式來(lái)表示,String.length返回的是Code Unit的長(zhǎng)度,而不再是Unicode中字符的長(zhǎng)度。對(duì)于傳統(tǒng)的BMP平面的代碼點(diǎn),String.length和我們傳統(tǒng)理解的字符的數(shù)量是一致的,對(duì)于擴(kuò)展的字符,String.length可能是我們理解的字符長(zhǎng)度的兩倍。

          有可能你會(huì)問(wèn), 對(duì)于一個(gè)UTF-16編碼的擴(kuò)展字符,它以4個(gè)字節(jié)來(lái)表示,那么前兩個(gè)字節(jié)會(huì)不會(huì)和BMP平面沖突,導(dǎo)致程序不知道它是擴(kuò)展字符還是BMP平面的字符?

          其實(shí)是不會(huì)的, 幸運(yùn)的是, 在BMP平面中,?U+D800U+DFFF之間的碼位是永久保留不映射到Unicode字符,UTF-16就利用保留下來(lái)的0xD800-0xDFFF區(qū)塊的碼位來(lái)對(duì)輔助平面的字符的碼位進(jìn)行編碼。

          UTF-16編碼中,輔助平面中的碼位從U+10000U+10FFFF,共計(jì)FFFFF個(gè),需要20位來(lái)表示。第一個(gè)整數(shù)(兩個(gè)字節(jié),稱為前導(dǎo)代理)要容納上述20位的前10位,第二個(gè)整數(shù)(稱為后尾代理)容納上述20位的后10位。前導(dǎo)代理的值的范圍是0xD8000xDBFF,后尾代理的0xDC00~0xDFFF。可以看到前導(dǎo)代理和后尾代理的范圍都落在了BMP平面中不用來(lái)映射的碼位,所以不會(huì)產(chǎn)生沖突,而且前導(dǎo)代理和后尾代理也沒(méi)有重合。這樣我們得到兩個(gè)字節(jié)的,就可以直接判斷它是否是BMP平面的字符,還是擴(kuò)展字符中的前導(dǎo)代理還是后尾代碼。

          國(guó)外的有些用戶用emojis字符做自己的昵稱,導(dǎo)致有些系統(tǒng)不能正確的顯示出來(lái),這是因?yàn)檫@些系統(tǒng)粗暴的使用Charactor來(lái)表示,在顯示的時(shí)候截?cái)嗟臅r(shí)候有時(shí)候可能不是在正確的代碼點(diǎn)上進(jìn)行截?cái)唷?/p>

          我們?cè)谶M(jìn)行字符串截取的時(shí)候,比如String.substring有可能會(huì)踩到一些坑,尤其經(jīng)常使用的emojis字符。

          自 Java 1.5 java.lang.String就提供了Code Point方法, 用來(lái)獲取完整的Unicode字符和Unicode字符數(shù)量:

          • public int codePointAt(int index)
          • public int codePointBefore(int index)
          • public int codePointCount(int beginIndex, int endIndex)

          注意這些方法中的index使用的是code unit值。

          來(lái)源 |?https://urlify.cn/qYNR3q

          END


          有熱門(mén)推薦?

          1.?性能提升360倍,瘋狂的4 次版本迭代!

          2.?一款vue編寫(xiě)的功能強(qiáng)大的swagger-ui,有點(diǎn)秀(附開(kāi)源地址)

          3.?分布式定時(shí)任務(wù)xxJob的常用姿勢(shì)都集齊了,So Easy!

          4.?為什么阿里規(guī)定需要在事務(wù)注解 @Transactional 中指定 rollbackFor?

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù)?Java?領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

          謝謝支持喲 (*^__^*)

          瀏覽 58
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本一级黄色视频 | 男人天堂AV电影 | 国产毛片基地 | 智光AV | 成人H动漫精品一区二区无码软件 |