我试图找出有效的数据类型。我知道 int 是 4 个字节,而 char 是一个字节。
- 一个包含五个整数的对象(4 * 5 = 20 字节)
- 一个有十个字符的 String 对象。(假设它有 10 个字符 10 * 1 = 10 个字节)
我对吗?你觉得哪一个更好?
我试图找出有效的数据类型。我知道 int 是 4 个字节,而 char 是一个字节。
我对吗?你觉得哪一个更好?
AString
不仅仅是一个字符数组,它是一个独立的对象,并且具有除 backing 之外的字段char[]
。例如,String
具有三个int
字段offset
:count
和hash
。因此,空字符串通常是 16 个字节(因为我们还需要考虑该char[]
字段)加上正常的 8 个字节的对象开销。另请注意, achar[]
本身就是一个对象,并且具有int
字段length
和关联的对象开销。考虑到所有这些因素后,您可以为每个字符添加两个(不是一个!)字节。
因此,对于 10 个字符的字符串:
int
字段:12个字节char[]
字段:8个字节
int
字段:4字节这大约有 60 个字节。我说“关于”是因为其中一些取决于 VM。
你对char
Java 中的 s 是不正确的:因为它们被设计为保存 16 位 UNICODE 代码点,所以它们占用两个,而不是一个字节。最后,两种表示将占用相同数量的内存。
您应该选择对您、类的设计者和代码的读者最有意义的数据类型。内存问题不应该是您设计的首要任务,除非您需要的对象数量可能会溢出您的可用内存。即使这样,您也应该在优化之前进行仔细的内存分析。
我知道 int 是 4 个字节
正确的
char 是一个字节。
Achar
是一个 16 位无符号整数,所以 2 个字节
一个包含五个整数的对象(4 * 5 = 20 字节)
AObject
有一个标头,在 32 位 JVM 上为 12 个字节,在 64 位 JVM 上为 16 个字节。对象是 8 字节对齐的,如果更改,可能是 16 或 32 字节对齐。
这意味着 anew int[5]
使用 16 + 20 + 4(填充)= 40 字节
一个有十个字符的 String 对象。(假设它有 10 个字符 10 * 1 = 10 个字节)
字符串使用 ~24 字节的标题和长度字段等,但它包装了一个包含实际字符的 char[],即另外 16+20+4 = 40 个字节。
一个简单的检查方法是使用以下方法。确保您使用-XX:-UseTLAB
which 改善内存记帐(但对于多线程编程来说较慢)
public static void main(String... ignored) {
char[] chars = new char[10];
long used = memoryUsed();
String s= new String(chars);
long diff = memoryUsed() - used;
if (diff == 0) throw new AssertionError("You must set -XX:-UseTLAB on the command line");
System.out.printf("Creating a String of 10 characters used %,d bytes of memory%n", diff);
}
private static long memoryUsed() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
印刷
Creating a String of 10 characters used 64 bytes of memory
字符大小为 2 个字节。它们等效于无符号短整数,因此字符的值可以介于 [0, 65535] 之间。
一个 String 占用的字节数实际上是:
string.length * 2
因此,对于您的示例,10 个字符的字符串占用 20 个字节,而不是 10 个字节。
这只是字符串内容。类中还有其他变量String
当然会占用更多字节。甚至一个空对象也会占用一定数量的字节,这将根据 JVM 实现而有所不同。
但是,仅字符内容将占用每个字符 2 个字节。
但是不要担心这是最可靠的过早优化。干净的代码通常比闪电般快速的代码更重要。选择合适的数据类型,编写易于理解和阅读的代码。这些东西更重要。
如果您担心在内存中保存大字符串,请考虑改变您的方法。我看到的大字符串最常见的问题是当新程序员将整个文件读入内存时。
如果您正在这样做,请尝试逐行处理数据。一次只在内存中保存您需要的最小单元,执行您的处理,然后继续。