美團面試官問我一個字符的String.length()是多少,我說是1,面試官說你回去好好學一下吧

本文首發於微信公衆號:程序員喬戈裏 html

public class testT {
    public static void main(String [] args){
        String A = "hi你是喬戈裏";
        System.out.println(A.length());
    }
}

以上結果輸出爲7。java

小萌邊說邊在IDEA中的win環境下選中String.length()函數,使用ctrl+B快捷鍵進入到String.length()的定義。程序員

/**
     * 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;
    }

接着使用google翻譯對這段英文進行了翻譯,獲得了大致意思:返回字符串的長度,這一長度等於字符串中的 Unicode 代碼單元的數目。面試

小萌:喬戈裏,那這又是啥意思呢? 喬哥:前幾天我寫的一篇文章:面試官問你編碼相關的面試題,把這篇甩給他就完事!裏面對於Java的字符使用的編碼有介紹:編程

Java中 有內碼和外碼這一區分簡單來講微信

  • 內碼:char或String在內存裏使用的編碼方式。
  • 外碼:除了內碼均可以認爲是「外碼」。(包括class文件的編碼)

而java內碼:unicode(utf-16)中使用的是utf-16. 因此上面的那句話再進一步解釋就是:返回字符串的長度,這一長度等於字符串中的UTF-16的代碼單元的數目。函數

代碼單元指一種轉換格式(UTF)中最小的一個分隔,稱爲一個代碼單元(Code Unit),所以,一種轉換格式只會包含整數個單元。UTF-X 中的數字 X 就是各自代碼單元的位數。this

UTF-16 的 16 指的就是最小爲 16 位一個單元,也即兩字節爲一個單元,UTF-16 能夠包含一個單元和兩個單元,對應便是兩個字節和四個字節。咱們操做 UTF-16 時就是以它的一個單元爲基本單位的。google

你還記得你前幾天被面試官說菜的時候學到的Unicode知識嗎,在面試官讓我講講Unicode,我講了3秒說沒了,面試官說你可真菜這裏面提到,UTF-16編碼一個字符對於U+0000-U+FFFF範圍內的字符采用2字節進行編碼,而對於字符的碼點大於U+FFFF的字符采用四字節進行編碼,前者是兩字節也就是一個代碼單元,後者一個字符是四字節也就是兩個代碼單元!編碼

而上面個人例子中的那個字符的Unicode值就是「U+1D11E」,這個Unicode的值明顯大於U+FFFF,因此對於這個字符UTF-16須要使用四個字節進行編碼,也就是使用兩個代碼單元!

因此你纔看到個人上面那個示例結果表示一個字符的String.length()長度是2!

來看個例子!

public class testStringLength {
    public static void main(String [] args){
        String B = "𝄞"; // 這個就是那個音符字符,只不過因爲當前的網頁沒支持這種編碼,因此沒顯示。
        String C = "\uD834\uDD1E";// 這個就是音符字符的UTF-16編碼
        System.out.println(C);
        System.out.println(B.length());
        System.out.println(B.codePointCount(0,B.length()));
        // 想獲取這個Java文件本身進行演示的,能夠在個人公衆號【程序員喬戈裏】後臺回覆 6666 獲取
    }
}

能夠看到經過codePointCount()函數得知這個音樂字符是一個字符!

幾個問題: 0.codePointCount是什麼意思呢? 1.以前不是說音符字符是「U+1D11E」,爲何UTF-16是"\uD834\uDD1E",這倆之間如何轉換? 2.前面說了UTF-16的代碼單元,UTF-32和UTF-8的代碼單元是多少呢?

一個一個解答:

第0個問題:

codePointCount其實就是代碼點數的意思,也就是一個字符就對應一個代碼點數。

好比剛纔音符字符(沒辦法打出來),它的代碼點是U+1D11E,但它的代理單元是U+D834和U+DD1E,若是令字符串str = "\u1D11E",機器識別的不是音符字符,而是一個代碼點」/u1D11「和字符」E「,因此會獲得它的代碼點數是2,代碼單元數也是2。

但若是令字符str = "\uD834\uDD1E",那麼機器會識別它是2個代碼單元代理,可是是1個代碼點(那個音符字符),故而,length的結果是代碼單元數量2,而codePointCount()的結果是代碼點數量1.

第1個問題

上圖是對應的轉換規則:

  • 首先 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 能夠包含一個單元,二個單元,三個單元及四個單元,對應便是一,二,三及四字節。

參考

本文首發於微信公衆號:程序員喬戈裏

若是是頭條用戶,能夠在個人頭條號程序員喬戈裏後臺回覆 資源獲取價值59998元的編程和考研資料 以爲文章不錯的歡迎關注個人WX公衆號:程序員喬戈裏
我是BAT大廠後臺開發工程師,,專一分享技術乾貨/編程資源/求職面試/成長感悟等,關注送5000G編程資源和本身整理的一份幫助很多人拿下java的offer的面經附答案,免費下載CSDN資源。

本文由博客一文多發平臺 OpenWrite 發佈!

相關文章
相關標籤/搜索