Java中字符編碼格式詳解
一、前言
在分析Comparable和Comparator的時候,分析到了String類的compareTo方法,String底層是用char[]數(shù)組來存放元素,在比較的時候是比較的兩個字符串的字符,字符用char來存儲,此時,突然想到,Java里面的char可以存放中文嗎?后來發(fā)現(xiàn)是可以的,并且由此也引出了Java中字符的編碼格式問題。
二、Java存儲格式
在Java中,如下代碼獲取了字符'張'的各種編碼格式。
import java.io.UnsupportedEncodingException;
public class Test {
public static String getCode(String content, String format) throws UnsupportedEncodingException {
byte[] bytes = content.getBytes(format);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
sb.append(Integer.toHexString(bytes[i] & 0xff).toUpperCase() + " ");
}
return sb.toString();
}
public static void main(String[] args) throws UnsupportedEncodingException {
System.out.println("gbk : " + getCode("張", "gbk"));
System.out.println("gb2312 : " + getCode("張", "gb2312"));
System.out.println("iso-8859-1 : " + getCode("張", "iso-8859-1"));
System.out.println("unicode : " + getCode("張", "unicode"));
System.out.println("utf-16 : " + getCode("張", "utf-16"));
System.out.println("utf-8 : " + getCode("張", "utf-8"));
}
}
運行結(jié)果:
gbk : D5 C5 gb2312 : D5 C5 iso-8859-1 : 3F unicode : FE FF 5F 20 utf-16 : FE FF 5F 20 utf-8 : E5 BC A0
說明:從結(jié)果我們可以知道,字符'張'的gbk與gb2312編碼是相同的,unicode與utf-16編碼時相同的,但是其iso-8859-1、unicode、utf-8編碼都是不相同的。那么,在JVM中,字符'張'是按照哪種編碼格式進行存儲的呢?下面開始我們的分析。
三、探秘思路
1. 查看.class文件常量池的存儲格式
測試代碼如下
public class Test {
public static void main(String[] args) {
String str = "張";
}
}
使用javap -verbose Test.class進行反編譯,發(fā)現(xiàn)常量池情況如下:

再使用winhex打開class文件,發(fā)現(xiàn)字符'張'在常量池的存儲如下

說明:上面兩張可以在class文件中是以utf-8的格式存儲的。
但是在運行時是否是utf-8格式呢?繼續(xù)我們的探秘之旅。
2. 在程序中一探究竟
使用如下代碼
public class Test {
public static void main(String[] args) {
String str = "張";
System.out.println(Integer.toHexString(str.codePointAt(0)).toUpperCase());
}
}
運行結(jié)果:
5F20
說明:根據(jù)結(jié)果我們知道在運行時JVM是使用的utf-16格式進行存儲,utf-16一般是使用2個字節(jié)進行存儲,如果遇到兩個字節(jié)無法表示的字符則會使用4個字節(jié)表示。之后會另外有篇幅進行介紹,并且我們查看Character類源碼時,會發(fā)現(xiàn)就是使用的utf-16進行編碼的,從兩面都找到了我們想要的答案。
3. char類型可以存放中文嗎?
根據(jù)上面的探索我們已經(jīng)知道了Java的class文件中字符是以utf-8進行編碼的,在JVM運行時則是以utf-16進行編碼存儲的。而字符'張'可以用兩個字節(jié)來表示,而char在Java中也是兩個字節(jié),故可以存放。
四、總結(jié)
經(jīng)過上面的分析,我們知道:
1. 字符在class文件中是以utf-8格式進行編碼的,而在JVM運行時是采用utf-16格式進行編碼的。
2. char類型是兩個字節(jié),可以用來存放中文。
在此次調(diào)用的過程中又查閱了好多關(guān)于字符方面的資料,受益匪淺,并且發(fā)現(xiàn)特別有意思,接下來會進行分享,所以特此預(yù)告下一篇將會進一步來介紹編碼以及編碼在Java中的問題。敬請期待
相關(guān)文章
SpringBoot集成PDFBox實現(xiàn)電子簽章的代碼詳解
Apache PDFBox 是一個開源的 Java 庫,用于處理 PDF 文檔,它提供了一系列強大的功能,包括創(chuàng)建、渲染、拆分、合并、加密、解密 PDF 文件,以及從 PDF 中提取文本和元數(shù)據(jù)等,本文給大家介紹了SpringBoot集成PDFBox實現(xiàn)電子簽章,需要的朋友可以參考下2024-09-09
IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項目實現(xiàn)動態(tài)登錄與注冊功能
這篇文章主要介紹了IDEA下創(chuàng)建SpringBoot+MyBatis+MySql項目實現(xiàn)動態(tài)登錄與注冊功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
解讀controller層,service層,mapper層,entity層的作用與聯(lián)系
這篇文章主要介紹了關(guān)于controller層,service層,mapper層,entity層的作用與聯(lián)系,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11

