欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java String保存字符串的機(jī)制

 更新時(shí)間:2021年05月20日 11:17:59   作者:守夜人愛吃兔子  
Java中字符串以什么格式來存儲(chǔ)?Java 中的 Unicode 字符串會(huì)按照 Latin1或者 UTF16 的編碼格式保存在 String 中,本文就詳細(xì)的介紹了一下,感興趣的可以了解一下

String 真的是 Immutable 的嗎

Java 中的 Unicode 字符串會(huì)按照 Latin1(所有的字符都小于 0xFF 時(shí))或者 UTF16 的編碼格式保存在 String 中,保存為 byte 數(shù)組:

private final byte[] value;

通常所說的 Immutable 都是指 final bytes 在 String 初始化后就不會(huì)修改,所有字符串的相關(guān)操作都是不會(huì)修改原數(shù)組而是創(chuàng)建新的副本。

但是數(shù)組元素理論上是可以修改的,比如下面通過反射的方式,將字符串常量 abc 修改為 Abc:

    public static void main(String[] args) {
     setFirstValueToA("abc");
        String replaced = new String("abc");
        System.out.println(replaced); // Abc
    }
    
    private static void setFirstValueToA(String str) {
        Class<String> stringClass = String.class;
        try {
            Field value = stringClass.getDeclaredField("value");
            value.setAccessible(true);
            byte[] bytes = (byte[]) value.get(str);
            bytes[0] = 0x41; // A
 
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

字符串?dāng)?shù)組如何保存為字節(jié)數(shù)組

通過如下代碼測試幾個(gè)字符串?dāng)?shù)組:

    public static void main(String[] args) {
        printString("abc");
        printString("中文");
        printString("abc中文");
        printString("abc");
    }
    private static void printString(String str) {
        System.out.println("======>" + str);
        // return the UTF-16 char[] size
        System.out.println("length: " + str.length());
        // Use default Encoding (UTF-8)
        System.out.println("getBytes: " + str.getBytes().length);
        // Convert UTF-16 char[] to char
        System.out.println("codePointCount: " + str.codePointCount(0, str.length()));
        // Get the UTF-16 char[]
        System.out.println("toCharArray: " + str.toCharArray().length);
        // The UTF-16 char[] to bytes
        System.out.println("internal value: " + getStringInternalValueLength(str));
    }

結(jié)果如下:

internal value

首先解釋下 String 的 value 字段計(jì)算方式:

  • 所有字符都小于 0xFF 時(shí),采用 Latin1 Character Encoding 來保存 Unicode code point,也就是每個(gè)字符都用一個(gè) byte 來保存。比如“ABC”
  • 上述條件不滿足時(shí),采用 UTF-16 Character Encoding 來保存,也就是每個(gè)字符都用 2 個(gè)或者 4 個(gè) byte 來保存。

Unicode 是 Coded Character Set,將幾乎所有的人類文字映射到 code point 符號,通常格式為 U+xxxx,xxxx 為 16 進(jìn)制整數(shù),表達(dá)范圍為 U+0000~U+10FFFF。code point 符號是文字的規(guī)范化標(biāo)記,但是實(shí)際保存時(shí)肯定還是要保存為字節(jié)數(shù)組的。這些不同的保存方式就是 Character Encoding,比如 UTF-8,還有 Java String 內(nèi)部采用的 UTF-16。

UTF-16 是一種將 Unicode code point 表達(dá)成字符數(shù)組的編碼方式,對于 U+0000~U+FFFF,直接按照 2 個(gè)字節(jié)保存(細(xì)分的話還有大端字節(jié)序和小端字節(jié)序的區(qū)別);對于 U+10000~U+10FFFF,會(huì)先轉(zhuǎn)化為一對 U+D800~U+DFFF 范圍內(nèi)的 code point(surrogate pair),再將這兩個(gè) code point 按照前面的規(guī)則保存。之所以選擇這個(gè)范圍,是因?yàn)檫@個(gè) Unicode 區(qū)間還沒有被分配有效的字符,因此可以和前面的規(guī)則區(qū)分。

“中文”這兩個(gè)漢字的 Unicode code point 非別為 U+4E2d、U+6587,大于 0xFF,所以保存 byte 長度為 4;"abc中文" 中存在不滿足條件的字符,所以全部用 UTF-16 保存,它們都是 2 個(gè) byte 的,所以長度為 10。

“☺” 的 Unicode code point 為 U+1F60A,根據(jù) UTF-16 規(guī)范,U+10000~U+10FFFF 需要轉(zhuǎn)化為 surrogate pair 之后再保存成 byte, 轉(zhuǎn)換后為 U+D83D、U+DE0A,因此 "abc" 的字節(jié)長度為 10。

toCharArray()

Java 中 char 的大小為 2 個(gè)字節(jié),剛好可以表示一個(gè) U+0000~U+FFFF 的 Unicode 符號。

Latin1 編碼時(shí),char 數(shù)組為 byte 數(shù)組的填充,高字節(jié)為 0;UTF-16 編碼時(shí),相當(dāng)于轉(zhuǎn)化過 surrogate pair 后的 Unicode 編碼數(shù)組,其中 0xD800~0xDFFF 范圍內(nèi)的為 surrogate 字符。

“abc” 時(shí)為 Latin1 編碼,所以 char 數(shù)組大小等于 bytes 數(shù)組;“abc中文” 時(shí)為 UTF-16 編碼,所以 char 數(shù)組大小等于 bytes 數(shù)組的一半。

codePointCount()

toCharArray 方法將轉(zhuǎn)化后的 surrogate pair 也算在內(nèi),因此實(shí)際長度可能大于字符長度。而 codePointCount 就能去除 surrogate pair 的影響,返回初始的字符長度,它會(huì)將連續(xù)兩個(gè) surrogate pair 只計(jì)數(shù)一次。

String.length

該方法就是 toCharArray 數(shù)組的長度,受到 surrogate pair 的影響,可能大于字符長度。

str.getBytes().length

String 內(nèi)部是通過 UTF-16 編碼保存的字節(jié)數(shù)組,當(dāng)通過 getBytes 方法返回時(shí),是需要指定 Encoding 的,默認(rèn)采用 UTF-8,因此會(huì)將 UTF-16 的字節(jié)數(shù)組轉(zhuǎn)化為 UTF-8 的字節(jié)數(shù)組,每個(gè) Unicode 符號在 UTF-8 編碼后長度為 1~4 字節(jié)。

        System.out.println("abc".getBytes(UTF_8).length); // 3
        System.out.println("中".getBytes(UTF_8).length); // 3
        System.out.println("文".getBytes(UTF_8).length); // 3
        System.out.println("".getBytes(UTF_8).length); // 4
 

最后

到此這篇關(guān)于Java String保存字符串的機(jī)制的文章就介紹到這了,更多相關(guān)Java String保存字符串內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC4 + MyBatis3 + SQL Server 2014整合教程(含增刪改查分頁)

    SpringMVC4 + MyBatis3 + SQL Server 2014整合教程(含增刪改查分頁)

    這篇文章主要給大家介紹了關(guān)于SpringMVC4 + MyBatis3 + SQL Server 2014整合的相關(guān)資料,文中包括介紹了增刪改查分頁等相關(guān)內(nèi)容,通過示例代碼介紹的非常詳細(xì),分享出來供大家參考學(xué)習(xí),下面來一起看看吧。
    2017-06-06
  • Spring循環(huán)依賴的處理方法

    Spring循環(huán)依賴的處理方法

    循環(huán)依賴是指兩個(gè)或多個(gè)組件之間相互依賴,形成一個(gè)閉環(huán),從而導(dǎo)致這些組件無法正確地被初始化或加載,這篇文章主要介紹了Spring循環(huán)依賴的處理,需要的朋友可以參考下
    2023-08-08
  • Spring Cloud Netflix架構(gòu)淺析(小結(jié))

    Spring Cloud Netflix架構(gòu)淺析(小結(jié))

    這篇文章主要介紹了Spring Cloud Netflix架構(gòu)淺析(小結(jié)),詳解的介紹了Spring Cloud Netflix的概念和組件等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java開發(fā)環(huán)境的完整搭建過程

    java開發(fā)環(huán)境的完整搭建過程

    這篇文章主要給大家介紹了關(guān)于java開發(fā)環(huán)境的完整搭建過程,文中介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • java實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換

    java實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換

    這篇文章主要為大家詳細(xì)介紹了java如何實(shí)現(xiàn)文件和base64相互轉(zhuǎn)換,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • Spring依賴注入底層原理詳解

    Spring依賴注入底層原理詳解

    這篇文章主要介紹了Spring依賴注入底層原理詳解,??依賴注入是一種設(shè)計(jì)模式,它將對象之間的依賴關(guān)系從代碼中移除,并由容器來管理這些依賴關(guān)系,依賴注入的主要目的是降低代碼的耦合度,使代碼更加靈活和可維護(hù),需要的朋友可以參考下
    2023-09-09
  • 在Spring Boot中如何使用log4j記錄日志

    在Spring Boot中如何使用log4j記錄日志

    這篇文章主要介紹如何在spring boot中引入log4j,以及一些基礎(chǔ)用法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • 淺談Java8對字符串連接的改進(jìn)正確姿勢

    淺談Java8對字符串連接的改進(jìn)正確姿勢

    這篇文章主要介紹了Java8:對字符串連接的改進(jìn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • JAVA文件讀取常用工具類(8種)

    JAVA文件讀取常用工具類(8種)

    JAVA操作文件在經(jīng)常會(huì)使用到,本文匯總了部分JAVA操作文件的讀取常用工具類,主要介紹了8種方法,具有一定的參考價(jià)值,感興趣的可以了解一下
    2021-08-08
  • 比較排序之冒泡排序的實(shí)現(xiàn)

    比較排序之冒泡排序的實(shí)現(xiàn)

    下面小編就為大家?guī)硪黄容^排序之冒泡排序的小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧實(shí)現(xiàn)。
    2017-06-06

最新評論