Java虚拟机规范指出,布尔类型的支持是有限的。
Java虚拟机没有专门用于布尔值操作的指令。相反,对布尔类型进行操作的Java编程语言表达式被编译为使用Java虚拟机int数据类型的值。
上述内容暗示(尽管我可能理解有误),当操作布尔类型时会使用int数据类型,但这是一个32位的内存构造。考虑到布尔只表示1位信息:
- 为什么不使用byte或short类型作为布尔的代理而选择了int呢?
- 对于任何给定的JVM,确定存储布尔类型所需的确切内存量的最可靠方法是什么?
就最小化布尔值使用的空间而言:对于大多数应用程序而言,这并不是一个问题。栈帧(保存本地变量和方法参数)并不是很大,在大范围内,对象中的离散布尔值也不是很大。如果您有许多带有许多布尔值的对象,则可以使用通过getter和setter管理的位字段。但是,您将支付一个在CPU时间上比在内存上罚款更大的惩罚。
回到一个布尔值占用多少的问题,是的它至少占用一个字节,但由于对齐规则,它可能会占用更多空间。我认为更有趣的是,一个布尔值数组将消耗每个条目一个字节,而不是一个比特,加上一些由于对齐和数组的大小字段而产生的开销。有些图算法需要大量的位字段,你需要知道,如果你使用布尔值数组,你需要几乎比实际需要的内存多8倍(1字节对1比特)。
中央处理器(CPU)的操作需要特定的数据类型长度。对于32位CPU,它们是32位长,因此在Java中称为'int'。如果长度低于或高于该长度,则必须将其填充或拆分为此长度,然后CPU才能处理它。这不需要花费太多时间,但如果您需要2个CPU周期而不是1个来执行基本操作,则意味着成本/时间加倍。
此规格专为32位CPU设计,以便它们可以使用其本机数据类型处理布尔值。
在速度和内存之间只能选择一个 - SUN选择了速度。
布尔映射是基于32位CPU设计的。int值有32位,因此可以在一次操作中处理。
以下是来自Peter Norvig的Java IAQ: Infrequently Answered Questions的解决方案,用于测量大小(略有不精确):
static Runtime runtime = Runtime.getRuntime();
...
long start, end;
Object obj;
runtime.gc();
start = runtime.freememory();
obj = new Object(); // Or whatever you want to look at
end = runtime.freememory();
System.out.println("That took " + (start-end) + " bytes.");
Empty.java
class Empty{
}
还有一个像这样的类:
NotEmpty.java
class NotEmpty{
boolean b;
}
boolean[]
和byte[]
的指令仍然与以前相同。但这并不意味着布尔数组必须使用每个元素一个字节的空间。使用相同的指令并不意味着指令必须执行相同的操作。就像无论字段的类型如何,只有一个getfield
指令用于读取字段一样。无论是baload
/bastore
指令引用的是boolean[]
还是byte[]
数组,都是已知的。但由于规范禁止字撕裂,实现必须选择一个支持原子读写访问的本机元素类型。 - undefined