現象:我們在編譯源文件EncodingTest.java時(shí),編譯通過(guò);但用java EncodigngTest解析EncdoingTest.class文件時(shí),總是顯示亂碼.
EncodingTest.java內容如下:
public class EncodingTest
{
public static void main(String args[])
{
System.out.println("A中國A");
}
}
執行javac EncodingTest后顯示如下:
理論上,應該是輸出 “A中國A”,那為什么會(huì )出現亂碼呢?
我們來(lái)看看從java源文件到解析生成class文件,這一過(guò)程發(fā)生了什么事情,如下圖: 
(1) 當我們執行javac命令時(shí),如果沒(méi)有指明encoding參數,編譯器就會(huì )把源文件當作GB2312編碼格式的文件編譯成為UTF-8編碼的class文件。
(2) 當我們執行java命令的時(shí)候,JVM把class文件的UTF-8字符轉化為UNICODE格式的編碼字符加載進(jìn)內存中.
顯然,解析class文件出現亂碼的源頭就是在編譯的時(shí)候.把上面的EncodingTest.java用記事本打開(kāi),點(diǎn)擊“文件”>>“另存為”,可以看到下圖:
所以原因就在于:我們的源文件的編碼格式為UTF-8,編譯器默認地把它當作GB2312的編碼格式編譯成class文件,必然會(huì )出現亂碼!
我們把上面的源文件記事本打開(kāi),“文件”>“另存為”然后直接按保存(備份源文件),再執行javac EncodingTest.java,發(fā)現編譯報錯,奇怪為什么同樣是一個(gè)UTF-8編碼的源文件,我們沒(méi)有作過(guò)任何修改,那為什么第一次執行通過(guò),而第二次執行會(huì )報錯呢?
用16進(jìn)制編輯軟件打開(kāi),發(fā)現我們第二次保存的源文件多了“EF BB BF”文件頭,所以原因很明顯:
當我們用javac編譯第一個(gè)源文件時(shí),由于沒(méi)有文件頭,所以可以把編譯器騙過(guò)去;但第二次保存的那個(gè)文件,由于多了UTF-8的文件頭,當編譯器用默認的GB2132來(lái)編譯源文件時(shí),發(fā)現文件頭是UTF-8的文件頭就認為我們是在騙它,所以徹底讓編譯不通過(guò)!
那么是不是我們指明編譯時(shí)源文件的編碼,編譯就可以通過(guò)且正確解析呢?用第二次保存的文件,我們執行javac –encoding UTF-8 EncodingTest.java,發(fā)現編譯不通過(guò);把文件頭刪去,再執行上面命令,發(fā)現編碼和解析都正常進(jìn)行,由此得知編譯器只認識沒(méi)有文件頭的UTF-8編碼格式文件!
由分析可知,如果一個(gè)java源文件通過(guò),但解析顯示出錯,那么極大可能是編譯時(shí)編碼轉化出了問(wèn)題!



