最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JDK9為何要將String的底層實現由char[]改成了byte[]

 更新時間:2022年03月25日 09:43:06   作者:公眾號_IT老哥  
String 類的源碼已經由?char[]?優(yōu)化為了?byte[]?來存儲字符串內容,為什么要這樣做呢?本文就詳細的介紹一下,感興趣的可以了解一下

如果你不是 Java8 的釘子戶,你應該早就發(fā)現了:String 類的源碼已經由 char[] 優(yōu)化為了 byte[] 來存儲字符串內容,為什么要這樣做呢?

開門見山地說,從 char[] 到 byte[],最主要的目的是為了節(jié)省字符串占用的內存。內存占用減少帶來的另外一個好處,就是 GC 次數也會減少。

一、為什么要優(yōu)化 String 節(jié)省內存空間

我們使用 jmap -histo:live pid | head -n 10 命令就可以查看到堆內對象示例的統(tǒng)計信息、查看 ClassLoader 的信息以及 finalizer 隊列。

以我正在運行著的編程喵喵項目實例(基于 Java 8)來說,結果是這樣的。

其中 String 對象有 17638 個,占用了 423312 個字節(jié)的內存,排在第三位。

由于 Java 8 的 String 內部實現仍然是 char[],所以我們可以看到內存占用排在第 1 位的就是 char 數組。

char[] 對象有 17673 個,占用了 1621352 個字節(jié)的內存,排在第一位。

那也就是說優(yōu)化 String 節(jié)省內存空間是非常有必要的,如果是去優(yōu)化一個使用頻率沒有 String 這么高的類庫,就顯得非常的雞肋。

二、byte[] 為什么就能節(jié)省內存空間呢?

眾所周知,char 類型的數據在 JVM 中是占用兩個字節(jié)的,并且使用的是 UTF-8 編碼,其值范圍在 '\u0000'(0)和 '\uffff'(65,535)(包含)之間。

也就是說,使用 char[] 來表示 String 就導致了即使 String 中的字符只用一個字節(jié)就能表示,也得占用兩個字節(jié)。

而實際開發(fā)中,單字節(jié)的字符使用頻率仍然要高于雙字節(jié)的。

當然了,僅僅將 char[] 優(yōu)化為 byte[] 是不夠的,還要配合 Latin-1 的編碼方式,該編碼方式是用單個字節(jié)來表示字符的,這樣就比 UTF-8 編碼節(jié)省了更多的空間。

換句話說,對于:

String name = "jack";  

這樣的,使用 Latin-1 編碼,占用 4 個字節(jié)就夠了。

但對于:

String name = "小二"; 

這種,木的辦法,只能使用 UTF16 來編碼。

針對 JDK 9 的 String 源碼里,為了區(qū)別編碼方式,追加了一個 coder 字段來區(qū)分。

/**  
 * The identifier of the encoding used to encode the bytes in  
 * {@code value}. The supported values in this implementation are  
 *  
 * LATIN1  
 * UTF16  
 *  
 * @implNote This field is trusted by the VM, and is a subject to  
 * constant folding if String instance is constant. Overwriting this  
 * field after construction will cause problems.  
 */  
private final byte coder; 

Java 會根據字符串的內容自動設置為相應的編碼,要么 Latin-1 要么 UTF16。

也就是說,從 char[] 到 byte[]中文是兩個字節(jié),純英文是一個字節(jié),在此之前呢,中文是兩個字節(jié),英文也是兩個字節(jié)。

三、為什么用UTF-16而不用UTF-8呢?

在 UTF-8 中,0-127 號的字符用 1 個字節(jié)來表示,使用和 ASCII 相同的編碼。只有 128 號及以上的字符才用 2 個、3 個或者 4 個字節(jié)來表示。

  • 如果只有一個字節(jié),那么最高的比特位為 0;

  • 如果有多個字節(jié),那么第一個字節(jié)從最高位開始,連續(xù)有幾個比特位的值為 1,就使用幾個字節(jié)編碼,剩下的字節(jié)均以 10 開頭。

具體的表現形式為:

  • 0xxxxxxx:一個字節(jié);

  • 110xxxxx 10xxxxxx:兩個字節(jié)編碼形式(開始兩個 1);- 1110xxxx 10xxxxxx 10xxxxxx:三字節(jié)編碼形式(開始三個 1);

  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字節(jié)編碼形式(開始四個 1)。

也就是說,UTF-8 是變長的,那對于 String 這種有隨機訪問方法的類來說,就很不方便。所謂的隨機訪問,就是charAt、subString這種方法,隨便指定一個數字,String要能給出結果。如果字符串中的每個字符占用的內存是不定長的,那么進行隨機訪問的時候,就需要從頭開始數每個字符的長度,才能找到你想要的字符。

那有小伙伴可能會問,UTF-16也是變長的呢?一個字符還可能占用 4 個字節(jié)呢?

的確,UTF-16 使用 2 個或者 4 個字節(jié)來存儲字符。

  • 對于 Unicode 編號范圍在 0 ~ FFFF 之間的字符,UTF-16 使用兩個字節(jié)存儲。

  • 對于 Unicode 編號范圍在 10000 ~ 10FFFF 之間的字符,UTF-16 使用四個字節(jié)存儲,具體來說就是:將字符編號的所有比特位分成兩部分,較高的一些比特位用一個值介于 D800DBFF 之間的雙字節(jié)存儲,較低的一些比特位(剩下的比特位)用一個值介于 DC00DFFF 之間的雙字節(jié)存儲。

但是在 Java 中,一個字符(char)就是 2 個字節(jié),占 4 個字節(jié)的字符,在 Java 里也是用兩個 char 來存儲的,而String的各種操作,都是以Java的字符(char)為單位的,charAt是取得第幾個char,subString取的也是第幾個到第幾個char組成的子串,甚至length返回的都是char的個數。

所以UTF-16在Java的世界里,就可以視為一個定長的編碼。

到此這篇關于JDK9為何要將String的底層實現由char[]改成了byte[]的文章就介紹到這了,更多相關JDK9 char[]改成了byte[]內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • SpringBoot @Validated注解實現參數分組校驗的方法實例

    SpringBoot @Validated注解實現參數分組校驗的方法實例

    這篇文章主要給大家介紹了關于SpringBoot @Validated注解實現參數分組校驗的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java?synchronized關鍵字性能考量及優(yōu)化探索

    Java?synchronized關鍵字性能考量及優(yōu)化探索

    這篇文章主要為大家介紹了Java?synchronized關鍵字性能考量及優(yōu)化探索示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Java之maven打完jar包之后將jar包放到指定位置匯總

    Java之maven打完jar包之后將jar包放到指定位置匯總

    這篇文章主要介紹了Java之maven打完jar包之后將jar包放到指定位置匯總,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • springboot?整合?SA-Token?使用詳解

    springboot?整合?SA-Token?使用詳解

    本文詳細介紹了SA-Token這款安全框架的使用,并結合實際操作演示了如何集成到springboot項目中,感興趣的朋友跟隨小編一起看看吧
    2024-08-08
  • 一文教你如何更改IDEA已有項目的路徑/名稱

    一文教你如何更改IDEA已有項目的路徑/名稱

    由于IDEA項目路徑中有中文、空格等特殊符號,影響正常使用,想要修改路徑名稱,怎么正確修改IDEA項目名稱,使其正常運行呢?所以本文小編講給大家詳細的介紹了更改IDEA已有項目的路徑/名稱解決方案,需要的朋友可以參考下
    2023-11-11
  • Spring框架中一個有用的小組件之Spring Retry組件詳解

    Spring框架中一個有用的小組件之Spring Retry組件詳解

    Spring Retry 是從 Spring batch 中獨立出來的一個功能,主要實現了重試和熔斷,對于那些重試后不會改變結果,毫無意義的操作,不建議使用重試,今天通過本文給大家介紹Spring Retry組件詳解,感興趣的朋友一起看看吧
    2021-07-07
  • java把excel內容上傳到mysql實例代碼

    java把excel內容上傳到mysql實例代碼

    這篇文章主要介紹了java把excel內容上傳到mysql實例代碼,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Java實現斷點下載功能的示例代碼

    Java實現斷點下載功能的示例代碼

    當下載一個很大的文件時,如果下載到一半暫停,如果繼續(xù)下載呢?斷點下載就是解決這個問題的。本文將用Java語言實現斷點下載,需要的可以參考一下
    2022-05-05
  • Java雜談之代碼重構的方法多長才算長

    Java雜談之代碼重構的方法多長才算長

    關于代碼重構的理解:在不改變軟件系統(tǒng)/模塊所具備的功能特性的前提下,遵循/利用某種規(guī)則,使其內部結構趨于完善。其在軟件生命周期中的價值體現主要在于可維護性和可擴展性
    2021-10-10
  • redis與ssm整合方法(mybatis二級緩存)

    redis與ssm整合方法(mybatis二級緩存)

    本文給大家介紹redis與ssm整合方法(mybatis二級緩存)。主要是利用redis去做mybatis的二級緩存,mybaits映射文件中所有的select都會刷新已有緩存,如果不存在就會新建緩存,所有的insert,update操作都會更新緩存
    2017-12-12

最新評論

奉化市| 桦甸市| 西乌珠穆沁旗| 太湖县| 石嘴山市| 克山县| 泰兴市| 宜春市| 安顺市| 石狮市| 岳普湖县| 连城县| 额尔古纳市| 仁化县| 甘孜县| 达孜县| 鹤峰县| 鄱阳县| 盐山县| 江北区| 民权县| 石家庄市| 抚宁县| 雅安市| 东光县| 深圳市| 乌拉特前旗| 曲靖市| 冀州市| 泰宁县| 乌鲁木齐县| 枣庄市| 宜州市| 合作市| 徐州市| 筠连县| 江达县| 积石山| 德安县| 仁化县| 肇庆市|