Java:8种基本数据类型及其所占内存字节数
内存中最基本的是二进制位,也就是比特(bit)。一个基本的数据单位是字节(byte),1byte = 8bit。注意:字节是内存最小寻址单位!
Java中有8种基本的数据类型,分别是:
逻辑:boolean;
整数:byte、short、int、long;
字符:char;
浮点:float、double。
八种数据类型所占用的内存大小(字节)分别为:
逻辑:boolean;
整数:byte-1、short-2、int-4、long-8;
字符:char-2;
浮点:float-4、double-8。
咦,可以看出来,只有boolean是没有说明的。那boolean是有多大呢?
查了一下,貌似这个问题还是个坑。在java中的 boolean 在内存中占多少字节?中讨论跟帖了好多。
boolean用true或false表示的是1bit的信息,这一点想必是没有问题的。
对于1bit的信息,理论上只需要占用1个bit位就可以表示了。但是,实际中是否真的占用1个bit位呢?之前的贴子里有说占1byte(8bit)的,使用最低位表示,其余为0;有说用int表示的。还有或用1bit表示的(这个应该就不对了,Java中字节是最小内存寻址单位)。
在Java的官方文档Primitive Data Types里,对boolean的描述如下:
boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.
可以看出,文中对int、char等的描述中都说明了占用字节数,唯独对boolean的描述中只是说,代表1bit的信息,但(内存)“大小”并没有精确定义。
猜测这是需要JVM自己定义优化 。
在stackoverflow上也有讨论的帖子What is the size of a boolean variable in java?,排在第一位的答案就一句话:
Its virtual machine dependent.
另一个投票很多的答案写了代码来测试,如下:
class LotsOfBooleans { boolean a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af; boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf; boolean c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf; boolean d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df; boolean e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; } class LotsOfInts { int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af; int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf; int c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, cb, cc, cd, ce, cf; int d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, da, db, dc, dd, de, df; int e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, ea, eb, ec, ed, ee, ef; } public class Test { private static final int SIZE = 1000000; public static void main(String[] args) throws Exception { LotsOfBooleans[] first = new LotsOfBooleans[SIZE]; LotsOfInts[] second = new LotsOfInts[SIZE]; System.gc(); long startMem = getMemory(); for (int i=0; i < SIZE; i++) { first[i] = new LotsOfBooleans(); } System.gc(); long endMem = getMemory(); System.out.println ("Size for LotsOfBooleans: " + (endMem-startMem)); System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE))); System.gc(); startMem = getMemory(); for (int i=0; i < SIZE; i++) { second[i] = new LotsOfInts(); } System.gc(); endMem = getMemory(); System.out.println ("Size for LotsOfInts: " + (endMem-startMem)); System.out.println ("Average size: " + ((endMem-startMem) / ((double)SIZE))); // Make sure nothing gets collected long total = 0; for (int i=0; i < SIZE; i++) { total += (first[i].a0 ? 1 : 0) + second[i].a0; } System.out.println(total); } private static long getMemory() { Runtime runtime = Runtime.getRuntime(); return runtime.totalMemory() - runtime.freeMemory(); } }
运行结果是:
Size for LotsOfBooleans: 87978576 Average size: 87.978576 Size for LotsOfInts: 328000000 Average size: 328.0
我之前使用过runtime.totalMemory() - runtime.freeMemory()来计算内存,不过感觉不太靠谱。因为分配的mem是根据需要变动的。不过看这个结果,在大量数据的时候还是可以的。
代码中的数组是80个,所以平均下来Boolean是1byte,Int是4byte。
不过也有人说在JVM中,boolean和boolean[]的处理是不一样的。正好有本《Java虚拟机规范(Java SE 7)》,查阅了下boolean章节如下:
虽然Java虚拟机定义了boolean这种数据类型, 只对它提供了非常有限的支持。在Java虚拟机中没有任何提供boolean值专用的字节码指令,在Java语言之中设及到boolean类型值的运算,在编译之后都使用Java虚拟机中的int数据类型来代替。
Java虚拟机直接支持boolean类型的数组,虚拟机的newarray指令可以创建这种数组。boolean的数组类型的访问与修改公用byte类型数组的baload和bastore指令。
这样一来,就比较明确了:
JVM中,对boolean的支持有限,所以是按照int处理的;对boolean数组是直接支持的,按照byte数组处理。
参考资料: