如果我们运行这行代码
long num = 5;
这个变量有64位空间吗?或者尺寸是由放在一边的值决定的?逻辑上它应该是64位,因为原始数据类型是可变的。但我的结论是真的吗?
此外,如果我们有一个不可变对象,如字符串
String str = "Hello World";
默认情况下,为此String提供最大内存似乎是反直觉的。如果您要设置一个字符串然后更改它,您只需将指针更改为第二个字符串的内存地址,即新创建的字符串。
有人可以回答这个问题或指出我正确的方向吗?
答案 0 :(得分:2)
long
是一个64-bit
原始值,无论您保留在哪个实际值内。
String
是一个包装char[]
的类。内部数组具有不同的大小,具体取决于内部的字符数。 16-bits
¹char
。
¹它比这复杂一点,但一般来说每个字符都是16位。
答案 1 :(得分:1)
整数类型是byte,short,int和long,其值分别是8位,16位,32位和64位二进制补码整数,以及char,其值为16-表示UTF-16代码单元的无符号整数(§3.1)。
浮点类型是float,其值包括32位IEEE 754浮点数和double,其值包括64位IEEE 754浮点数。
显然,这些基元能够具有最小值和最大值,它们需要由固定数量的内存表示,因此它不能变化。
关于String
,每个对象都有一个char[]
(直到JDK 9),它有一个固定的长度。
答案 2 :(得分:1)
有不同类型的变量,因此,没有一个答案。
堆变量,也称为字段,通常具有与数据类型匹配的大小,有时甚至更多,具体取决于对齐注意事项,但始终足以保存数据的任何有效值类型。正如您已经提到的那样,引用类型指向堆内存中的对象并为其分配另一个引用只是更改地址,因此引用类型的变量具有可以存储的固定大小堆内存地址¹,与引用对象的大小无关。由于String
实例是不可变的,因此重新分配是更改String
变量的唯一方法。
对于局部变量,图片是不同的。在这里,处理速度比减少内存消耗更重要。因此,数据类型boolean
,byte
,short
,char
和int
均统一视为int
,您已经注意到了在源代码级别上,因为对这些数据类型(boolean
除外)所做的所有算术都会产生int
。这种转换已经在编译时发生。在运行时优化代码时,JVM可以重新建立较小的存储类型,但这不是通常的方向。局部变量更可能映射到CPU寄存器,根本没有任何存储。或者,如果将寄存器计为存储器,则它们至少为32位宽,而在当今大多数系统中为64位。
要继续使用long num = 5;
示例,像HotSpot这样的JVM使用Static single assignment form之类的优化,这样可以处理num
的后续读取,就像它们使用常量5
一样因此,由于其实际价值,他们可以像int
那样对待它,但通常,效果是用可预测的结果取代计算,这样就不需要存储值了。
¹堆不必像理论上可寻址的内存一样大,因此只要堆较小,具有 CompressedOOPs 的JVM在64位体系结构上仅使用32位进行对象引用比 alignment ×2³²,即32GiB与默认对齐。