Java:Char与字符串字节大小

Java:Char与字符串字节大小,java,string,char,byte,Java,String,Char,Byte,我惊讶地发现以下代码 System.out.println("Character size:"+Character.SIZE/8); System.out.println("String size:"+"a".getBytes().length); 输出如下: 字符大小:2 字符串大小:1 我假设一个字符串应该比一个字符占用相同(或更多)的字节 我特别想知道 如果我有一个包含多个字段的JavaBean,那么它的大小将如何增加取决于字段

我惊讶地发现以下代码

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

字符大小:2

字符串大小:1

我假设一个字符串应该比一个字符占用相同(或更多)的字节

我特别想知道

如果我有一个包含多个字段的JavaBean,那么它的大小将如何增加取决于字段的性质(字符、字符串、布尔值、向量等)。我假设所有java对象都有一些(可能是最小的)足迹,并且这些足迹中最小的一个将是单个字符。为了测试这个基本假设,我从上面的代码开始——打印语句的结果似乎违反直觉


了解java在默认情况下存储/序列化字符与字符串的方式将非常有用。

getBytes()
使用默认编码(很可能是
ISO-8859-1
)输出
字符串,而内部字符字符始终有2个字节。Java内部使用始终字符数组和2字节字符,如果您想了解更多有关编码的信息,请阅读问题注释中的Oded链接。

字符大小是字符所需的存储空间,为16位。字符串的长度(也是基础字符数组或字节数组的长度)是字符数(或字节数),而不是以位为单位的大小

这就是为什么你要用8除法来计算尺寸,而不是长度。长度需要乘以2

还请注意,如果指定不同的编码,则将获得字节数组的其他长度。在本例中,在执行getBytes()时执行了到单个或可变大小编码的转换


请参阅:)

我想说出我的想法,如果我错了,请纠正我,但您找到的字符串长度是正确的,它显示为1,因为字符串中只有1个字符。长度显示长度,而不是大小。长度和大小是两码事


检查这个。。您发现以错误的方式占用的字节数

好吧,字符数组中的1个字符的大小为2个字节,字符串包含的长度为1个字符,而不是1个字节

Java中的
字符串
对象包括:

private final char value[];
private final int offset;
private final int count;
private int hash;
只有这样才能确保
String
对象比
char
数组大。
如果您想了解更多有关对象大小的信息,还可以阅读有关对象头和字符数组的多重性因子的信息。例如或。

我想先添加一些代码,然后再做一些解释:

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:

因此,前2个字节:feff是发送以下字节为UTF-16 Big-Endian的信号所必需的。请参阅维基百科页面了解更多信息

剩下的2个字节:0061是字符“a”的2个字节表示形式。可通过以下方式进行验证:


是的,Java中的一个字符是2个字节,但是当您请求没有特定编码的字节时,您可能不会总是得到2个字节,因为不同的编码将需要不同数量的字节用于不同的字符

字符串的长度是它包含的字符数。一个字符可以用多个字节编码。字符串很可能是UTF-8编码的,所以“A”只需要一个字节。@NiklasB。或者更确切地说是固定宽度的UTF-16(UCS-2)类型格式。不,他使用了
getBytes()
,所以他得到的实际上是字节数(这也不足为奇)。是的,这个答案有点离题,并且错误地描述了这个问题。。。我建议进行更新。作为参考,
getBytes()
实际上并没有告诉您
字符串的实际内存消耗量。我认为您的这句话不正确:“Java内部总是使用带有2字节字符的字符数组。”您可以看到以下链接:对于我,Java在代码中使用UTF-8作为默认编码。@KorayTugay您可能混淆了Unicode在Java中的内部内存表示形式(是的,每个字符序列实现(如String)仍然使用UTF-16格式的2字节字符),以及Java在特定字节编码中导入或导出内部表示形式(文件、网络)。如果您仍然相信您的Java版本(即…?)在内部使用UTF-8,您如何证明这一点?顺便说一句,getBytes()的问题是该函数非常古老,在版本1.1中,UTF-8还不受支持时就已经存在了,因此您无法真正预测它是否使用UTF-8。这没有意义。您是否可以尝试改进语法。。。等