java int short区别,优化 - 为什么Java API使用int而不是short或byte?

优化 - 为什么Java API使用int而不是short或byte?

为什么Java API使用short,int甚至byte就足够了?

示例:类short中的short字段使用short。

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

6个解决方案

162 votes

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

所以更深入一层:答案可能只与Java虚拟机指令集有关。 如Java虚拟机规范中的表所总结,所有积分算术运算(如添加,除法等)仅适用于类型Calendar.DAY_OF_WEEK和类型byte,而不适用于较小类型。

(旁白:较小的类型(Calendar.DAY_OF_WEEK和byte)基本上只用于数组。像int这样的数组将占用1000个字节,像double这样的数组将占用4000个字节)

当然,现在,人们可以说“......明显的下一个问题是:为什么这些说明仅适用于Calendar.DAY_OF_WEEK(和byte)?”。

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

如果每个类型指令都支持所有Java虚拟机运行时数据类型,那么将会有更多指令,而不是在一个字节中表示

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

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

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

Marco13 answered 2019-05-27T07:03:57Z

37 votes

(差不多)所有操作byte,short会将它们推广到int,例如,你不能写:

short x = 1;

short y = 2;

short z = x + y; //error

使用byte时,算术更简单直接,无需施法。

在空间方面,它会产生很小的差异。 byte和short会使事情复杂化,我不认为这个微优化是值得的,因为我们正在谈论固定数量的变量。

byte在为嵌入式设备编程或处理文件/网络时相关且有用。 这些原语也是有限的,如果计算可能会超出他们未来的限制怎么办? 试着考虑short类的扩展,它可能会发展更大的数字。

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

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

另一方面,在数组中,byte占用1个字节,short取2个字节,int占用4个字节,因为在数组中只有开始,也许它的结尾必须对齐。 这将在您想要使用的情况下产生影响,例如,System.arraycopy(),那么您将真正注意到性能差异。

Maroun answered 2019-05-27T07:05:10Z

7 votes

因为与短裤相比,使用整数时算术运算更容易。 假设常量确实由int值建模。 然后你必须以这种方式使用API:

short month = Calendar.JUNE;

month = month + (short) 1; // is july

注意显式铸造。 在算术运算中使用时,短值会隐式提升为int。 (在操作数堆栈上,短路甚至表示为整数。)这将使用起来非常麻烦,这就是为什么short值通常是常量的首选。

与此相比,存储效率的提高是最小的,因为只存在固定数量的这种常数。 我们谈论的是40个常数。 将存储空间从int更改为short可以保护您的安全40 * 16 bit = 80 byte.有关详细信息,请参阅此答案。

Rafael Winterhalter answered 2019-05-27T07:05:54Z

5 votes

如果你使用了积分常量存储在它们所适合的最小类型中的哲学,那么Java会有一个严重的问题:每当程序员使用积分常量编写代码时,他们必须仔细注意他们的代码以检查是否有类型 常量很重要,如果是这样,请查看文档中的类型和/或进行所需的任何类型转换。

既然我们已经概述了一个严重的问题,那么您希望通过这种理念获得哪些好处? 我不会感到惊讶的是,如果通过反射查看常量,那么该变化的唯一运行时可观察效果将是您获得的类型。 (当然,懒惰/不知情程序员引入的错误不能正确地解释常量的类型)

权衡利弊是非常容易的:这是一个糟糕的哲学。

Hurkyl answered 2019-05-27T07:06:39Z

4 votes

虚拟机的设计复杂性取决于它可以执行多少种操作。对于32位整数,64位整数,32位浮点和64位浮点数这样的指令实现四次实现更容易,此外还要比以上是较小数值类型的版本。一个更有趣的设计问题是为什么应该有四种类型,而不是更少(使用64位整数执行所有整数计算和/或使用64位浮点值执行所有浮点计算)。使用32位整数的原因是,预计Java可以在许多平台上运行,其中32位类型可以像16位或8位类型一样快速地运行,但64位类型的操作会明显慢点。即使在16位类型可以更快使用的平台上,使用32位数量的额外成本也会被仅具有32位类型所提供的简单性所抵消。

至于在32位值上执行浮点计算,优点有点不太清楚。在某些平台上,通过将所有操作数转换为更高精度类型,添加它们,然后将结果转换回32位浮点数进行存储,可以最快速地执行byte之类的计算。在其他平台上,使用32位浮点值执行所有计算会更有效。 Java的创建者决定要求所有平台以相同的方式执行操作,并且他们应该支持32位浮点计算比更长的计算机更快的硬件平台,即使这种速度严重降低了PC的速度在典型的PC上,以及在没有浮点单元的许多机器上,浮点数学的精度和精度。注意,顺便说一句,取决于b,c和d的值,当计算像上述long这样的表达式时,使用更高精度的中间计算有时会产生比所有中间操作数实现的结果更精确的结果。 byte精度,但有时会产生一个稍微不那么准确的值。无论如何,Sun决定一切都应该以同样的方式完成,并且他们选择使用最小精度long值。

请注意,当大量数据类型以数组形式存储在一起时,较小数据类型的主要优点变得明显; 即使单个变量的类型小于64位没有优势,也值得拥有可以更紧凑地存储更小值的数组; 有一个局部变量是byte而不是long节省七个字节; 具有1,000,000个数字的数组将每个数字保持为byte,而不是long波长7,000,000个字节。 由于每个数组类型只需要支持一些操作(最明显的是读取一个项目,存储一个项目,复制数组中的一系列项目,或将一系列项目从一个数组复制到另一个数组),增加了更多的复杂性 阵列类型不像具有更多类型的可直接使用的离散数值的复杂性那么严重。

supercat answered 2019-05-27T07:07:31Z

2 votes

实际上,有一个小优势。 如果你有

class MyTimeAndDayOfWeek {

byte dayOfWeek;

byte hour;

byte minute;

byte second;

}

然后在典型的JVM上,它需要与包含单个DAY_OF_WEEK的类一样多的空间。内存消耗将四舍五入到8或16字节的下一个倍数(IIRC,这是可配置的),因此存在实际保存的情况相当罕见。

如果相应的DAY_OF_WEEK方法返回byte,则此类稍微容易使用。但是没有这样的Calendar方法,只有get(int)因为其他字段必须返回int。 较小型号的每个操作都升级到int,因此您需要大量的铸造。

最有可能的是,你要么放弃并切换到DAY_OF_WEEK,要么写出像

void setDayOfWeek(int dayOfWeek) {

this.dayOfWeek = checkedCastToByte(dayOfWeek);

}

那么DAY_OF_WEEK的类型无关紧要。

maaartinus answered 2019-05-27T07:08:32Z

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值