Java語言中一個字符占幾個字節?


要區分清楚內碼(internal encoding)和外碼(external encoding)就好了。

內碼是程序內部使用的字符編碼,特別是某種語言實現其char或String類型在內存里用的內部編碼;
外碼是程序與外部交互時外部使用的字符編碼。“外部”相對“內部”而言;不是char或String在內存里用的內部編碼的地方都可以認為是“外部”。例如,外部可以是序列化之后的char或String,或者外部的文件、命令行參數之類的。

Java語言規范規定,Java的char類型是UTF-16的code unit,也就是一定是16位(2字節);

char, whose values are 16-bit unsigned integers representing UTF-16 code units ( §3.1).

然后字符串是UTF-16 code unit的序列:

The Java programming language represents text in sequences of 16-bit code units, using the UTF-16 encoding.

這樣,Java規定了字符的內碼要用UTF-16編碼。或者至少要讓用戶無法感知到String內部采用了非UTF-16的編碼。

 

另舉一例:
Java標准庫實現的對char與String的序列化規定使用UTF-8作為外碼。Java的Class文件中的字符串常量與符號名字也都規定用UTF-8編碼。這大概是當時設計者為了平衡運行時的時間效率(采用定長編碼的UTF-16)與外部存儲的空間效率(采用變長的UTF-8編碼)而做的取舍。
作者:國棟
鏈接:https://www.zhihu.com/question/27562173/answer/76208352
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
 

首先,你所謂的“字符”具體指什么呢?

如果你說的“字符”就是指 Java 中的 char,那好,那它就是 16 位,2 字節。

如果你說的“字符”是指我們用眼睛看到的那些“抽象的字符”,那么,談論它占幾個字節是沒有意義的。

具體地講,脫離具體的編碼談某個字符占幾個字節是沒有意義的

就好比有一個抽象的整數“42”,你說它占幾個字節?這得具體看你是用 byte,short,int,還是 long 來存它。用 byte 存就占一字節,用 short 存就占兩字節,int 通常是四字節,long 通常八字節。當然,如果你用 byte,受限於它有限的位數,有些數它是存不了的,比如 256 就無法放在一個 byte 里了。

字符是同樣的道理,如果你想談“占幾個字節”,就要先把編碼說清楚。

同一個字符在不同的編碼下可能占不同的字節

就以你舉的“ ”字為例,“ ”在 GBK 編碼下占 2 字節,在 UTF-16 編碼下也占 2 字節,在 UTF-8 編碼下占 3 字節,在 UTF-32 編碼下占 4 字節。

不同的字符在同一個編碼下也可能占不同的字節

”在 UTF-8 編碼下占3字節,而“ A”在 UTF-8 編碼下占 1 字節。(因為 UTF-8 是 變長編碼)

而 Java 中的 char 本質上是 UTF-16 編碼。而 UTF-16 實際上也是一個變長編碼(2 字節或 4字節)。

如果一個抽象的字符在 UTF-16 編碼下占 4 字節,顯然它是不能放到 char 中的。換言之, char 中只能放 UTF-16 編碼下只占 2 字節的那些字符。

而 getBytes 實際是做編碼轉換,你應該顯式傳入一個參數來指定編碼,否則它會使用缺省編碼來轉換。

你說“ new String("字").getBytes().length 返回的是3 ”,這說明缺省編碼是 UTF-8.如果你顯式地傳入一個參數,比如這樣“ new String("字").getBytes(" GBK").length ”,那么返回就是 2.

你可以在啟動 JVM 時設置一個缺省編碼,

假設你的類叫 Main,那么在命令行中用 java 執行這個類時可以通過 file.encoding 參數設置一個缺省編碼。比如這樣:java -D file.encoding= GBKMain這時,你再執行不帶參數的 getBytes() 方法時,new String("字").getBytes().length 返回的就是 2 了,因為現在缺省編碼變成 GBK 了。當然,如果這時你顯式地指定編碼,new String("字").getBytes(" UTF-8").length 返回的則依舊是 3.

否則,會使用所在操作系統環境下的缺省編碼。

通常,Windows 系統下是 GBK,Linux 和 Mac 是 UTF-8.但有一點要注意,在 Windows 下使用 IDE 來運行時,比如 Eclipse,如果你的工程的缺省編碼是 UTF-8,在 IDE 中運行你的程序時,會加上上述的 -D file.encoding= UTF-8 參數,這時,即便你在 Windows 下,缺省編碼也是 UTF-8,而不是 GBK。

由於受啟動參數及所在操作系統環境的影響,不帶參數的 getBytes 方法通常是不建議使用的,最好是顯式地指定參數以此獲得穩定的預期行為。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM