2012-03-22 66 views
7

嗨,大家好:我很驚訝地發現,下面的代碼Java:Char與字節字節大小。

System.out.println("Character size:"+Character.SIZE/8); 
System.out.println("String size:"+"a".getBytes().length); 

輸出這樣的:

字符大小:2

字符串大小:1

我會假定單個字符串應占用與單個字符相同(或更多)的字節。

特別是即時知道---

如果我有一個Java bean與它的幾個領域,其規模將如何取決於字段(字符,字符串,布爾,矢量等自然增長..)我假設所有的java對象都有一些(可能很小)的腳印,並且這些腳印中最小的一個將是單個字符。所以,爲了測試這個基本假設,我開始使用上面的代碼 - 並且打印語句的結果似乎違反直覺。

默認情況下,Java存儲/序列化字符與字符串的方式的任何見解將是非常有益的...謝謝。

+5

字符串的長度是它包含的字符數。一個字符可以用多於一個字節編碼。 – Oded 2012-03-22 15:23:01

+4

字符串最可能是UTF-8編碼,所以「a」只需要一個字節。 – 2012-03-22 15:23:12

+4

[絕對最小每個軟件開發人員絕對,肯定必須知道Unicode和字符集(沒有藉口!)](http://www.joelonsoftware.com/articles/Unicode.html) – Oded 2012-03-22 15:23:55

回答

10

getBytes()使用默認編碼輸出String(最可能是ISO-8859-1),而內部字符char始終爲2個字節。如果你想了解更多關於編碼的知識,Java內部總是使用帶有2字節字符的char數組,如果在問題註釋中讀到Oded的鏈接。

+3

作爲參考,'getBytes()'實際上並不告訴你'String'的實際內存消耗。 – 2012-03-22 15:25:55

+0

我不認爲你的這個陳述是正確的:「內部Java使用總是具有2字節字符的char數組。你可以看到這個鏈接:http://javarevisited.blogspot.com.tr/2012/01/get-set-default-character-encoding.html對於我來說,Java在代碼中使用UTF-8作爲默認編碼。 – 2016-01-21 09:14:49

+0

@KorayTugay您可能混淆了Java中Unicode的內部內存表示(是的,像String這樣的每個CharSequence實現仍然使用2字節的UTF-16格式字符),並且Java導入或導出內部表示(文件,網絡)在特定的字節編碼。如果你仍然相信你的Java版本(這是...?)在內部使用UTF-8,你是如何證明這一點的?順便說一句,getBytes()的問題在於函數很舊,當UTF-8尚未得到支持時它已經在1.1版本中,所以你不能真正預測它使用UTF-8。 – 2016-01-22 13:16:10

-1

字符的大小是16位字符所需的存儲空間。字符串的長度(也是底層字符數組或字節數組的長度)是字符數(或字節數),而不是位數。

這就是爲什麼你已經做了8除了大小,但不是長度的劃分。長度需要乘以2。

另請注意,如果您指定不同的編碼,您將獲得字節數組的其他長度。在這種情況下,執行getBytes()時將執行單一或變化大小的編碼轉換。

參見:http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#getBytes(java.nio.charset.Charset

+0

不,他使用'getBytes()',所以他得到的實際上是字節數(這也不奇怪)。 – 2012-03-22 15:25:27

+0

是的,這個答案有點偏離主題,並且錯誤地表達了問題...我建議更新。 – jayunit100 2012-03-24 16:41:48

2

我想說出我的想法,糾正我,如果我錯了,但是你發現這是正確的它顯示爲1,你只有1個字符的字符串的長度在字符串中。長度顯示長度不是大小。長度和大小是兩個不同的東西。

檢查這個Link ..你發現在錯誤的道路

0

以及佔用的字節數,你有1個字符的字符數組具有2個字節的大小和你的字符串包含爲1個字符長,而不是它有1個字節的大小。

String對象在Java中包括:

private final char value[]; 
private final int offset; 
private final int count; 
private int hash; 

只有這應該向你保證,反正String對象是更大然後char陣列。 如果您想了解更多關於對象大小的信息,您還可以閱讀關於char數組的對象標題和多重因子。例如herehere

+0

這沒有任何意義,你可以嘗試改進語法...等等? – jayunit100 2012-03-22 20:07:36

0

我想先添加一些代碼,然後稍微解釋一下:

import java.nio.charset.Charset; 

public class Main { 

    public static void main(String[] args) { 
     System.out.println("Character size: " + Character.SIZE/8); 
     final byte[] bytes = "a".getBytes(Charset.forName("UTF-16")); 
     System.out.println("String size: " + bytes.length); 
     sprintByteAsHex(bytes[0]); 
     sprintByteAsHex(bytes[1]); 
     sprintByteAsHex(bytes[2]); 
     sprintByteAsHex(bytes[3]); 
    } 

    static void sprintByteAsHex(byte b) { 
     System.out.print((Integer.toHexString((b & 0xFF)))); 
    } 
} 

和輸出將是:

Character size: 2 
String size: 4 
feff061 

那麼你實際上缺少的是,你沒有提供對getBytes方法的任何參數。可能,您正在獲取字符'a'的UTF-8表示字節。

那麼,爲什麼當我們要求UTF-16時,我們得到了4個字節呢?好的,Java在內部使用UTF-16,那麼我們應該得到2個字節嗎?

如果您檢查輸出:

feff061 

Java的實際返回了我們一個BOM:https://en.wikipedia.org/wiki/Byte_order_mark

所以前2個字節:feff是需要的信號,後面的字節將是UTF-16 Big Endian。請參閱維基百科頁面以獲取更多信息。

其餘的2個字節:0061是字符「a」的2字節表示形式。可以驗證來自:http://www.fileformat.info/info/unicode/char/0061/index.htm

所以是的,Java中的字符是2個字節,但是當您詢問沒有特定編碼的字節時,您可能並不總是獲得2個字節,因爲不同的編碼將需要不同數量的字節字符。