溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

一個Java字符串中有多少個字符

發(fā)布時間:2021-08-31 09:31:28 來源:億速云 閱讀:140 作者:chen 欄目:編程語言

本篇內(nèi)容主要講解“一個Java字符串中有多少個字符”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“一個Java字符串中有多少個字符”吧!

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

  • 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

首先,讓我們先看個例子:

public class Main {     public static void main(String[] args) {         // 中文常見字         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();     } }

運行這個程序,你覺得輸出結(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會使用操作系統(tǒng)的編碼格式得到字節(jié)數(shù)組,在我的MacOS中,默認(rèn)使用UTF-8作為字符編碼(locale命令可以查看操作系統(tǒng)的編碼),所以在我的機(jī)器運行,String.getBytes()會返回UTF-8編碼的字節(jié)數(shù)組。

  • String.length返回Unicode code units的長度。

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

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

  • 普通的中文字:字符串的長度是2,每個中文字按UTF-8編碼是三個字節(jié),字符數(shù)組的長度看起來也沒問題

  • emojis字符: 我們設(shè)置了兩個emojis字符,男女頭像。結(jié)果字符串的長度是4, UTF-8編碼8個字節(jié),字符數(shù)組的長度是4

  • 生僻的中文字:我們設(shè)置了兩個中文字,其中一個是生僻的中文字。結(jié)果字符串的長度是3, UTF-8編碼7個字節(jié),字符數(shù)組的長度是3

看起來字符串的字符數(shù)和我們預(yù)期的有點不一樣,我們的字符串只有兩個unicode字符, 可是輸出結(jié)果有時候是2,有時候是3, 有時候是4,為什么呢?

這還得從Java的歷史說起。

Java最初設(shè)計的Charactor用兩個字節(jié)來表示unicode字符,這沒有問題, 因為最初unicode中的字符還比較少, 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開始支持Unicode 4.0。

直到Unicode 3.0, Java用兩個字節(jié)來表示unicode字符還沒有問題,因為Unicode 3.0最多49,259個字符,  兩個字節(jié)可以表示65,535個字符,還足夠容的下所有的uicode3.0字符。

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

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

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

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

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

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

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

其實是不會的, 幸運的是, 在BMP平面中,  U+D800到U+DFFF之間的碼位是***保留不映射到Unicode字符,UTF-16就利用保留下來的0xD800-0xDFFF區(qū)塊的碼位來對輔助平面的字符的碼位進(jìn)行編碼。

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

國外的有些用戶用emojis字符做自己的昵稱,導(dǎo)致有些系統(tǒng)不能正確的顯示出來,這是因為這些系統(tǒng)粗暴的使用Charactor來表示,在顯示的時候截斷的時候有時候可能不是在正確的代碼點上進(jìn)行截斷。

到此,相信大家對“一個Java字符串中有多少個字符”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI