<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
如果你不是 Java8 的釘子戶,你應該早就發現了:String 類的原始碼已經由 char[]
優化為了 byte[]
來儲存字串內容,為什麼要這樣做呢?
開門見山地說,從 char[]
到 byte[]
,最主要的目的是為了節省字串佔用的記憶體。記憶體佔用減少帶來的另外一個好處,就是 GC 次數也會減少。
我們使用 jmap -histo:live pid | head -n 10
命令就可以檢視到堆內物件範例的統計資訊、檢視 ClassLoader 的資訊以及 finalizer 佇列。
以我正在執行著的程式設計喵喵專案範例(基於 Java 8)來說,結果是這樣的。
其中 String 物件有 17638 個,佔用了 423312 個位元組的記憶體,排在第三位。
由於 Java 8 的 String 內部實現仍然是 char[]
,所以我們可以看到記憶體佔用排在第 1 位的就是 char 陣列。
char[]
物件有 17673 個,佔用了 1621352 個位元組的記憶體,排在第一位。
那也就是說優化 String 節省記憶體空間是非常有必要的,如果是去優化一個使用頻率沒有 String 這麼高的類庫,就顯得非常的雞肋。
眾所周知,char 型別的資料在 JVM 中是佔用兩個位元組的,並且使用的是 UTF-8 編碼,其值範圍在 'u0000'(0)和 'uffff'(65,535)(包含)之間。
也就是說,使用 char[]
來表示 String 就導致了即使 String 中的字元只用一個位元組就能表示,也得佔用兩個位元組。
而實際開發中,單位元組的字元使用頻率仍然要高於雙位元組的。
當然了,僅僅將 char[]
優化為 byte[]
是不夠的,還要配合 Latin-1 的編碼方式,該編碼方式是用單個位元組來表示字元的,這樣就比 UTF-8 編碼節省了更多的空間。
換句話說,對於:
String name = "jack";
這樣的,使用 Latin-1 編碼,佔用 4 個位元組就夠了。
但對於:
String name = "小二";
這種,木的辦法,只能使用 UTF16 來編碼。
針對 JDK 9 的 String 原始碼裡,為了區別編碼方式,追加了一個 coder 欄位來區分。
/** * 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[]
,中文是兩個位元組,純英文是一個位元組,在此之前呢,中文是兩個位元組,英文也是兩個位元組。
在 UTF-8 中,0-127 號的字元用 1 個位元組來表示,使用和 ASCII 相同的編碼。只有 128 號及以上的字元才用 2 個、3 個或者 4 個位元組來表示。
如果只有一個位元組,那麼最高的位元位為 0;
如果有多個位元組,那麼第一個位元組從最高位開始,連續有幾個位元位的值為 1,就使用幾個位元組編碼,剩下的位元組均以 10 開頭。
具體的表現形式為:
0xxxxxxx:一個位元組;
110xxxxx 10xxxxxx:兩個位元組編碼形式(開始兩個 1);- 1110xxxx 10xxxxxx 10xxxxxx:三位元組編碼形式(開始三個 1);
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四位元組編碼形式(開始四個 1)。
也就是說,UTF-8 是變長的,那對於 String 這種有隨機存取方法的類來說,就很不方便。所謂的隨機存取,就是charAt、subString這種方法,隨便指定一個數位,String要能給出結果。如果字串中的每個字元佔用的記憶體是不定長的,那麼進行隨機存取的時候,就需要從頭開始數每個字元的長度,才能找到你想要的字元。
那有小夥伴可能會問,UTF-16也是變長的呢?一個字元還可能佔用 4 個位元組呢?
的確,UTF-16 使用 2 個或者 4 個位元組來儲存字元。
對於 Unicode 編號範圍在 0 ~ FFFF 之間的字元,UTF-16 使用兩個位元組儲存。
對於 Unicode 編號範圍在 10000 ~ 10FFFF 之間的字元,UTF-16 使用四個位元組儲存,具體來說就是:將字元編號的所有位元位分成兩部分,較高的一些位元位用一個值介於 D800DBFF 之間的雙位元組儲存,較低的一些位元位(剩下的位元位)用一個值介於 DC00DFFF 之間的雙位元組儲存。
但是在 Java 中,一個字元(char)就是 2 個位元組,佔 4 個位元組的字元,在 Java 裡也是用兩個 char 來儲存的,而String的各種操作,都是以Java的字元(char)為單位的,charAt是取得第幾個char,subString取的也是第幾個到第幾個char組成的子串,甚至length返回的都是char的個數。
所以UTF-16在Java的世界裡,就可以視為一個定長的編碼。
到此這篇關於JDK9為何要將String的底層實現由char[]改成了byte[]的文章就介紹到這了,更多相關JDK9 char[]改成了byte[]內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45