为什么Java API使用int而不是短字节或字节?

2022-08-31 07:57:28

为什么Java API使用,什么时候甚至就足够了?intshortbyte

示例:类“日历”中的“DAY_OF_WEEK”字段使用 。int

如果差异太小,那么为什么这些数据类型(,)存在呢?shortint


答案 1

一些原因已经指出。例如,“...(几乎)所有对字节的操作,short都会将这些原语提升为int”。但是,显而易见的下一个问题是:为什么这些类型被提升为?int

因此,更深入一层:答案可能只是与Java虚拟机指令集有关。正如 Java 虚拟机规范中的表中总结的那样,所有整型算术运算(如加法、除法等)仅适用于类型和类型,而不适用于较小的类型。intlong

(顺便说一句:较小的类型(字节)基本上只适用于数组。像 new byte[1000] 这样的数组需要 1000 个字节,而像 new int[1000] 这样的数组需要 4000 个字节。

当然,现在可以说“...显而易见的下一个问题是:为什么这些指令只针对int(和long)提供?

上面提到的JVM规范中提到了一个原因:

如果每个类型化指令都支持 Java 虚拟机的所有运行时数据类型,则指令将超过一个字节所能表示的指令。

此外,Java 虚拟机可以被视为真实处理器的抽象。为较小的类型引入专用的算术逻辑单元也不值得:它需要额外的晶体管,但它仍然只能在一个时钟周期内执行一个加法。设计JVM时的主要架构是32位,正好适合32位 。(涉及 64 位值的操作作为特例实现)。intlong

(注意:最后一段有点过于简单,考虑到可能的矢量化等,但应该给出基本的想法,而不必深入到处理器设计主题中)


编辑:一个简短的附录,侧重于问题中的示例,但在更一般的意义上:人们也可以问,使用较小的类型存储字段是否无益。例如,人们可能认为可以通过存储为 .但是在这里,Java类文件格式开始发挥作用:类文件中的所有字段至少占用一个“插槽”,其大小为一(32位)。(“宽”字段和 占用两个槽)。因此,显式声明字段为或不保存任何内存。Calendar.DAY_OF_WEEKbyteintdoublelongshortbyte


答案 2

(几乎)上的所有操作都会将它们提升为 ,例如,您不能编写:byteshortint

short x = 1;
short y = 2;

short z = x + y; //error

算术在使用时更容易和直接,无需转换。int

就空间而言,它几乎没有什么区别。 而且会使事情复杂化,我认为这种微优化不值得,因为我们谈论的是固定数量的变量。byteshort

byte当您为嵌入式设备编程或处理文件/网络时,它是相关且有用的。此外,这些基元是有限的,如果计算将来可能超过其限制怎么办?试着考虑一个类的扩展,它可能会演变成更大的数字。Calendar

另请注意,在 64 位处理器中,局部变量将保存在寄存器中,并且不会使用任何资源,因此使用 和其他基元根本不会有任何区别。此外,许多 Java 实现对齐变量*(和对象)。intshort


*byte并占用与局部变量,变量甚至实例变量相同的空间。为什么?因为在(大多数)计算机系统中,变量地址是对齐的,所以例如,如果你使用一个字节,你实际上最终会得到两个字节 - 一个用于变量本身,另一个用于填充。shortint

另一方面,在数组中,取1个字节,取2个字节,取4个字节,因为在数组中,只有开头和结尾必须对齐。例如,如果您想要使用,这将有所作为,那么您确实会注意到性能差异。byteshortintSystem.arraycopy()


推荐