Java中String的數據是如何存儲的,查看源代碼就可以知道,String的數據是存儲在char[] value這樣一個成員變量中的,char類型的大小在java中是2個字節
我們還知道,現在普遍使用的unicode版本是UCS-2,就是使用2個字節表示一個字符的unicode版本,這就對上了,java使用的就是UCS-2標准,所以,String中的value中存儲的都是一個個數字
比如’你’的unicode編碼是4f60,看下面的測試代碼
char c = '你';
System.out.println(Integer.toHexString(c));
System.out.println(Integer.valueOf(c));
System.out.println(c);
結果是:
4f60
20320
你
所以呢,現在我們知道了String內部其實存儲的是未經任何編碼的unicode編碼,就是那個對應字符的編碼,然後再看我們這兩個方法:
getBytes(charsetname)
意思是根據這個編碼來獲取字節數組
這又是什麼意思呢?
就是說將內存中的unicode編碼轉換為charsetname格式所對應的字節數組
比如’你’,轉換為utf-8是三個字接,所以得到的字節數組就是三個字節的
即[e4 bd a0]
然後String(bytes,charsetname)呢
意思就是將bytes這個字節數組按照charsetname解釋,組裝為一個String保存起來
例如上面那個字節數組[e4 bd a0],按照utf-8解釋的話,存儲起來就是”你”這個字符串,如果按照其他編碼解釋,則不會解釋為”你”
說個其他的,為什麼在servlet中處理參數一般都需要這麼一句了來控制編碼:
String str = new String(param.getBytes(“ISO-8859-1”),”UTF-8”);
其實這很好理解,浏覽器傳過來的字節數據是UTF-8編碼的,然後web容器默認這個字節數據是ISO-8859-1編碼的,所以使用ISO-8859-1把這個字節數據轉換變成了String存儲起來,相當於是進行了下面這個操作:
String s = new String(UTF8Bytes,”ISO-8859-1”);
注意這個編碼是單字節的,也就是將每一個字節都轉換成了unicode編碼,幸好是這樣,使我們有機會將這個String再轉換成和原來一模一樣的字節數組,所以才有了我們平時用的最多的那一句編碼處理的代碼
最後,想再說一下,對編碼這塊不了解的原因,是我們理解錯誤,我們必須知道的是:
java內部存儲字符串使用的unicode編碼
我們通常會聽到有人說:“我需要將String由ISO-8859-1轉換為GBK編碼”,這又是怎麼回事呢?實際上,我們並不是要“將 一個由ISO-8859-1編碼的String轉換為GBK編碼的String”,反復說明的是,JAVA中的String都是unicode編碼的,所以不存在“ISO- 8859-1編碼的String”或“GBK編碼的String”這樣的說法。而需要轉換的唯一的原因是String進行了錯誤的編碼。我們經常會碰到由ISO-8859- 1轉換為諸如GBK/UTF-8等等這樣的需求。所謂的轉換過程是:String –> byte[] –>String