int
,而不是仅使用short
或甚至byte
?例如,在
Calendar
类中,DAY_OF_WEEK
字段使用int
。如果差异太小,那么这些数据类型(
short
,int
)为什么还存在?int
,而不是仅使用short
或甚至byte
?Calendar
类中,DAY_OF_WEEK
字段使用int
。short
,int
)为什么还存在?int
?int
类型和long
类型,而不适用于较小的类型。byte
和short
)基本上只用于数组。像new byte[1000]
这样的数组将占用1000字节,而像new int[1000]
这样的数组将占用4000字节)
当然,人们可能会问:"...显然下一个问题是:为什么这些指令只提供给int
(和long
)?"。
其中一个原因在上面提到的JVM规范中提到:
此外,Java虚拟机可以被视为真实处理器的抽象。为较小类型引入专用算术逻辑单元将不值得花费精力:它需要额外的晶体管,但仍然只能在一个时钟周期内执行一次加法。当JVM设计时,占主导地位的架构是32位,非常适合32位如果每个类型的指令都支持Java虚拟机的所有运行时数据类型,则会有比一个字节表示更多的指令
int
。(涉及64位long
值的操作作为特殊情况实现)。(注:最后一段有点过于简化,考虑到可能的向量化等内容,但应该在不深入处理器设计主题的情况下提供基本思路)
编辑:一个简短的补充,侧重于问题中的示例,但从更一般的意义上来说:人们还可以问是否存储小型类型的字段会有益处。例如,人们可能认为通过将Calendar.DAY_OF_WEEK
存储为byte
可以节省内存。但是,在这里,Java类文件格式发挥作用:所有类文件中的字段都占用至少一个“插槽”,其大小为一个int
(32位)。 (“宽”字段,double
和long
,占用两个插槽)。因此,显式声明字段为short
或byte
也不会节省任何内存。
(几乎) 所有关于 byte
, short
的操作都会将它们提升为 int
类型,例如,你不能这样写:
short x = 1;
short y = 2;
short z = x + y; //error
当使用int
时,算术运算更加容易和直接,不需要进行强制转换。
在空间方面,这只会有非常小的影响。 byte
和short
会使事情变得复杂,我不认为这种微小优化值得,因为我们正在讨论固定数量的变量。
byte
在编写嵌入式设备程序或处理文件/网络时是相关和有用的。此外,这些基元是有限的,如果将来计算可能超出它们的限制怎么办?尝试考虑一下Calendar
类的扩展,它可能演变成更大的数字。
还要注意,在64位处理器中,局部变量将保存在寄存器中,并且不会使用任何资源,因此使用int
、short
和其他基元根本没有任何区别。此外,许多Java实现对齐变量*(和对象)。
*如果它们是局部变量、类变量或甚至实例变量,byte
和short
占用与int
相同的空间。为什么?因为在(大多数)计算机系统中,变量地址是对齐的,因此例如如果使用单个字节,则实际上会得到两个字节-一个用于变量本身,另一个用于填充。
另一方面,在数组中,byte
占用1个字节,short
占用2个字节,int
占用4个字节,因为在数组中只需要对开头和可能的结尾进行对齐。这将在您想要使用例如System.arraycopy()
时有所不同,然后您真的会注意到性能差异。
使用整数进行算术运算比使用短整型更容易。假设常量确实是由short
值建模的。那么您需要以以下方式使用API:
short month = Calendar.JUNE;
month = month + (short) 1; // is july
float a=b+c+d;
表达式时,使用高精度中间计算有时会产生显着更准确的结果,而如果所有中间操作数都以float
精度计算,则有时会得到略微不太准确的值。无论如何,Sun决定一切都应该以相同的方式完成,并选择使用最小精度的float
值。byte
而不是long
可以节省7个字节;将1,000,000个数字的数组中的每个数字都保存为byte
而不是long
可以节省7,000,000个字节。由于每种数组类型只需要支持一些操作(最重要的是读取一个项目、存储一个项目、在数组中复制一系列项目或从一个数组中复制一系列项目),因此拥有更多的数组类型的增加复杂性并不像直接可用的离散数值的更多类型的复杂性那样严重。
class MyTimeAndDayOfWeek {
byte dayOfWeek;
byte hour;
byte minute;
byte second;
}
int
的类一样多。内存消耗会四舍五入到8或16字节的下一个倍数(如果我没记错的话,这是可配置的),因此真正节省空间的情况相当罕见。Calendar
方法返回一个byte
,那么该类将稍微更易于使用。但是,只有get(int)
这样的Calendar
方法,并且必须返回int
,因为还有其他字段。对较小类型的每个操作都会提升为int
,因此需要进行大量转换。int
,要么编写如下的setter:void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
无论是哪种类型的DAY_OF_WEEK
,都没有关系。
Byte
表示月份中的某一天也不是必要的,因为对编译器来说它的意思是“请添加特殊行为以确保在 255 处溢出”,而不是“提醒一下,这个值非常小”。最简单的类型并不总是最受限制的类型。我曾经和一个非常好的同事讨论过,如果你知道元素是不同的,那么使用 Set
还是 List
更好,这个讨论沿着同样的线路进行;-) - Stefan Paul Noack
int
的大小。如果您有其他实现的参考,请更新答案并相应地插入链接。 - Marco13