Why does the Java API use int
, when short
or even byte
would be sufficient?
为什么Java API使用int,而短字节甚至字节就足够了?
Example: The DAY_OF_WEEK
field in class Calendar
uses int
.
示例:类日历中的DAY_OF_WEEK字段使用int。
If the difference is too minimal, then why do those datatypes (short
, int
) exist at all?
如果差异太小,那么为什么会存在这些数据类型(short, int)呢?
6 个解决方案
#1
160
Some of the reasons have already been pointed out. For example, the fact that "...(Almost) All operations on byte, short will promote these primitives to int". However, the obvious next question would be: WHY are these types promoted to int
?
一些原因已经被指出。例如,“……(几乎)所有字节上的操作,short都会将这些原语提升为int”。然而,显而易见的下一个问题是:为什么这些类型被提升为int类型?
So to go one level deeper: The answer may simply be related to the Java Virtual Machine Instruction Set. As summarized in the Table in the Java Virtual Machine Specification, all integral arithmetic operations, like adding, dividing and others, are only available for the type int
and the type long
, and not for the smaller types.
所以去更深一层:答案可能仅仅是相关的Java虚拟机指令集。在总结表中Java虚拟机规范,所有积分运算操作,比如添加、分裂和其他人,只是用于int类型和类型长,而不是为较小的类型。
(An aside: The smaller types (byte
and short
) are basically only intended for arrays. An array like new byte[1000]
will take 1000 bytes, and an array like new int[1000]
will take 4000 bytes)
(顺便说一句:较小的类型(字节和短类型)基本上只用于数组。像new byte[1000]这样的数组需要1000字节,而像new int[1000]这样的数组需要4000字节)
Now, of course, one could say that "...the obvious next question would be: WHY are these instructions only offered for int
(and long
)?".
现在,当然,人们可以说“……”显而易见的下一个问题是:为什么这些指令只针对int(和long)?
One reason is mentioned in the JVM Spec mentioned above:
上面提到的JVM规范中提到了一个原因:
If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte
如果每个类型化指令都支持Java虚拟机的所有运行时数据类型,那么将会有比字节中表示的更多的指令
Additionally, the Java Virtual Machine can be considered as an abstraction of a real processor. And introducing dedicated Arithmetic Logic Unit for smaller types would not be worth the effort: It would need additional transistors, but it still could only execute one addition in one clock cycle. The dominant architecture when the JVM was designed was 32bits, just right for a 32bit int
. (The operations that involve a 64bit long
value are implemented as a special case).
此外,可以将Java虚拟机视为一个真实处理器的抽象。为更小的类型引入专门的算术逻辑单元是不值得的:它需要额外的晶体管,但它仍然只能在一个时钟周期中执行一个加法。在设计JVM时,主要的架构是32位的,刚好适合32位的int(涉及64位长值的操作是作为特殊情况实现的)。
(Note: The last paragraph is a bit oversimplified, considering possible vectorization etc., but should give the basic idea without diving too deep into processor design topics)
(注意:考虑到可能的矢量化等因素,最后一段有点过于简化,但是应该给出基本的思想,而不要深入到处理器设计主题)
EDIT: A short addendum, focussing on the example from the question, but in an more general sense: One could also ask whether it would not be beneficial to store fields using the smaller types. For example, one might think that memory could be saved by storing Calendar.DAY_OF_WEEK
as a byte
. But here, the Java Class File Format comes into play: All the Fields in a Class File occupy at least one "slot", which has the size of one int
(32 bits). (The "wide" fields, double
and long
, occupy two slots). So explicitly declaring a field as short
or byte
would not save any memory either.
编辑:一个简短的附录,关注问题中的示例,但从更一般的意义上来说:还可以问,使用较小的类型存储字段是否有益。例如,有人可能认为可以通过存储日历来保存内存。DAY_OF_WEEK字节。但在这里,Java类文件格式发挥了作用:类文件中的所有字段至少占用一个“槽”,其大小为一个int(32位)。(“宽”字段,双长,占用两个槽)。因此显式地将字段声明为短或字节也不会保存任何内存。
#2
37
(Almost) All operations on byte
, short
will promote them to int
, for example, you cannot write:
(几乎所有字节上的操作,short都会将它们提升到int,例如,你不能写:
short x = 1;
short y = 2;
short z = x + y; //error
Arithmetics are easier and straightforward when using int
, no need to cast.
使用int类型时,算术更简单和直接,不需要强制转换。
In terms of space, it makes a very little difference. byte
and short
would complicate things, I don't think this micro optimization worth it since we are talking about a fixed amount of variables.
就空间而言,它没有多大区别。字节和短将使事情变得复杂,我认为这种微观优化不值得,因为我们讨论的是固定数量的变量。
byte
is relevant and useful when you program for embedded devices or dealing with files/networks. Also these primitives are limited, what if the calculations might exceed their limits in the future? Try to think about an extension for Calendar
class that might evolve bigger numbers.
当您为嵌入式设备编程或处理文件/网络时,字节是相关的和有用的。同样,这些原语也是有限的,如果将来的计算可能会超出它们的极限呢?尝试考虑一个日历类的扩展,它可能会进化出更大的数字。
Also note that in a 64-bit processors, locals will be saved in registers and won't use any resources, so using int
, short
and other primitives won't make any difference at all. Moreover, many Java implementations align variables* (and objects).
还要注意,在64位处理器中,局部变量将保存在寄存器中,不会使用任何资源,因此使用int、short和其他原语根本没有什么区别。此外,许多Java实现将变量*(和对象)对齐。
*byte
and short
occupy the same space as int
if they are local variables, class variables or even instance variables. Why? Because in (most) computer systems, variables addresses are aligned, so for example if you use a single byte, you'll actually end up with two bytes - one for the variable itself and another for the padding.
*如果是局部变量、类变量,甚至是实例变量,那么byte和short与int占用相同的空间。为什么?因为在(大多数)计算机系统中,变量地址是对齐的,因此,例如,如果您使用一个字节,那么实际上您将得到两个字节——一个用于变量本身,另一个用于填充。
On the other hand, in arrays, byte
take 1 byte, short
take 2 bytes and int
take four bytes, because in arrays only the start and maybe the end of it has to be aligned. This will make a difference in case you want to use, for example, System.arraycopy()
, then you'll really note a performance difference.
另一方面,在数组中,字节取1个字节,短取2个字节,int取4个字节,因为在数组中,只有开始和结束必须对齐。如果您想要使用System.arraycopy(),那么这将会产生很大的差异,然后您将真正注意到性能的差异。
#3
7
Because arithmetic operations are easier when using integers compared to shorts. Assume that the constants were indeed modeled by short
values. Then you would have to use the API in this manner:
因为与short相比,使用整数更容易进行算术运算。假设这些常量确实是由短值建模的。那么你就必须以这种方式使用API:
short month = Calendar.JUNE;
month = month + (short) 1; // is july
Notice the explicit casting. Short values are implicitly promoted to int
values when they are used in arithmetic operations. (On the operand stack, shorts are even expressed as ints.) This would be quite cumbersome to use which is why int
values are often preferred for constants.
注意到明确的铸件。在算术操作中,短值被隐式地提升为int值。(在操作数堆栈上,short甚至被表示为int。)这将是非常麻烦的使用,这就是为什么int值通常是首选的常量。
Compared to that, the gain in storage efficiency is minimal because there only exists a fixed number of such constants. We are talking about 40 constants. Changing their storage from int
to short
would safe you 40 * 16 bit = 80 byte
. See this answer for further reference.
与之相比,存储效率的提高是最小的,因为只有固定数量的这样的常量。我们讨论的是40个常数。将它们的存储从int改为short将安全的您40 * 16位= 80字节。请参阅此答案以作进一步参考。
#4
5
If you used the philosophy where integral constants are stored in the smallest type that they fit in, then Java would have a serious problem: whenever programmers write code using integral constants, they have to pay careful attention to their code to check if the type of the constants matter, and if so look up the type in the documentation and/or do whatever type conversions are needed.
如果你用哲学,积分常数存储在最小的类型,他们适应,那么Java有一个严重的问题:每当程序员编写代码使用积分常数,他们必须注意他们的代码检查常量的类型,如果是查找文档中的类型和/或做任何类型转换是必要的。
So now that we've outlined a serious problem, what benefits could you hope to achieve with that philosophy? I would be unsurprised if the only runtime-observable effect of that change would be what type you get when you look the constant up via reflection. (and, of course, whatever errors are introduced by lazy/unwitting programmers not correctly accounting for the types of the constants)
既然我们已经勾勒出了一个严重的问题,那么你希望用这种哲学来实现什么好处呢?如果更改的唯一运行时可观察的影响是通过反射查找常量时得到的类型,我不会感到惊讶。(当然,懒惰/不知情的程序员引入的任何错误都不能正确地解释常量的类型)
Weighing the pros and the cons is very easy: it's a bad philosophy.
权衡利弊很容易:这是一种糟糕的哲学。
#5
4
The design complexity of a virtual machine is a function of how many kinds of operations it can perform. It's easier to having four implementations of an instruction like "multiply"--one each for 32-bit integer, 64-bit integer, 32-bit floating-point, and 64-bit floating-point--than to have, in addition to the above, versions for the smaller numerical types as well. A more interesting design question is why there should be four types, rather than fewer (performing all integer computations with 64-bit integers and/or doing all floating-point computations with 64-bit floating-point values). The reason for using 32-bit integers is that Java was expected to run on many platforms where 32-bit types could be acted upon just as quickly as 16-bit or 8-bit types, but operations on 64-bit types would be noticeably slower. Even on platforms where 16-bit types would be faster to work with, the extra cost of working with 32-bit quantities would be offset by the simplicity afforded by only having 32-bit types.
虚拟机的设计复杂性取决于它能执行多少种操作。像“相乘”这样的指令有四种实现——一种是32位整数、64位整数、32位浮点数和64位浮点数——要比除了上面提到的,还有更小的数值类型的版本要容易得多。一个更有趣的设计问题是,为什么应该有四种类型,而不是更少(使用64位整数执行所有整数计算并/或使用64位浮点值执行所有浮点计算)。使用32位整数的原因是,Java被期望在许多平台上运行,在这些平台上,32位类型可以像16位或8位类型一样快速地执行操作,但是对64位类型的操作要明显地慢。即使在使用16位类型更快的平台上,使用32位数量的额外成本也会被只有32位类型的简单性所抵消。
As for performing floating-point computations on 32-bit values, the advantages are a bit less clear. There are some platforms where a computation like float a=b+c+d;
could be performed most quickly by converting all operands to a higher-precision type, adding them, and then converting the result back to a 32-bit floating-point number for storage. There are other platforms where it would be more efficient to perform all computations using 32-bit floating-point values. The creators of Java decided that all platforms should be required to do things the same way, and that they should favor the hardware platforms for which 32-bit floating-point computations are faster than longer ones, even though this severely degraded PC both the speed and precision of floating-point math on a typical PC, as well as on many machines without floating-point units. Note, btw, that depending upon the values of b, c, and d, using higher-precision intermediate computations when computing expressions like the aforementioned float a=b+c+d;
will sometimes yield results which are significantly more accurate than would be achieved of all intermediate operands were computed at float
precision, but will sometimes yield a value which is a tiny bit less accurate. In any case, Sun decided everything should be done the same way, and they opted for using minimal-precision float
values.
对于在32位值上执行浮点计算,优势就不那么明显了。有一些平台,比如浮点a=b+c+d;可以通过将所有操作数转换为更高精度的类型,添加它们,然后将结果转换回32位浮点数进行存储,从而最快地执行。还有其他平台可以更有效地使用32位浮点值执行所有计算。Java决定所有平台的创造者应该需要做同样的方式,他们应该支持32位浮点计算的硬件平台比时间更快,尽管这严重退化的电脑的速度和精度浮点数学在一个典型的电脑,以及许多机器没有浮点单元。请注意,顺便说一下,这取决于b、c和d的值,在计算上述浮点a=b+c+d这样的表达式时,使用更高精度的中间计算;有时会产生比所有中间操作数都要精确得多的结果,这些结果在浮点精度下被计算,但有时会产生一个稍微不那么精确的值。无论如何,Sun决定所有的事情都应该以同样的方式进行,他们选择使用最小精度浮点值。
Note that the primary advantages of smaller data types become apparent when large numbers of them are stored together in an array; even if there were no advantage to having individual variables of types smaller than 64-bits, it's worthwhile to have arrays which can store smaller values more compactly; having a local variable be a byte
rather than an long
saves seven bytes; having an array of 1,000,000 numbers hold each number as a byte
rather than a long
waves 7,000,000 bytes. Since each array type only needs to support a few operations (most notably read one item, store one item, copy a range of items within an array, or copy a range of items from one array to another), the added complexity of having more array types is not as severe as the complexity of having more types of directly-usable discrete numerical values.
请注意,较小数据类型的主要优势在大量存储在数组中时变得很明显;即使拥有小于64位的类型的单个变量没有好处,也值得拥有能够更紧凑地存储较小值的数组;使局部变量为字节而不是长变量可以节省7个字节;拥有1,000,000个数字的数组将每个数字作为一个字节保存,而不是一个7,000,000字节的长波浪。因为每个数组类型只需要支持一些操作(尤其是读一项,存储一个项目,复制数组内的物品,或复制的项目从一个到另一个数组),添加更多的数组类型的复杂性不是那么严重的复杂性有更多类型的直接使用离散的数值。
#6
2
Actually, there'd be a small advantage. If you have a
事实上,有一个小优势。如果你有一个
class MyTimeAndDayOfWeek {
byte dayOfWeek;
byte hour;
byte minute;
byte second;
}
then on a typical JVM it needs as much space as a class containing a single int
. The memory consumption gets rounded to a next multiple of 8 or 16 bytes (IIRC, that's configurable), so the cases when there are real saving are rather rare.
然后在一个典型的JVM上,它需要的空间与一个包含单个int的类一样多,内存消耗被四舍五入到下一个8或16字节的倍数(IIRC,这是可配置的),所以真正的保存是非常罕见的。
This class would be slightly easier to use if the corresponding Calendar
methods returned a byte
. But there are no such Calendar
methods, only get(int)
which must returns an int
because of other fields. Each operation on smaller types promotes to int
, so you need a lot of casting.
如果相应的日历方法返回一个字节,那么这个类会更容易使用。但是没有这样的日历方法,只有get(int),因为其他字段必须返回int。对较小类型的每个操作都提升为int类型,因此需要大量的强制转换。
Most probably, you'll either give up and switch to an int
or write setters like
最可能的情况是,您要么放弃并切换到int类型,要么像这样编写setter
void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
Then the type of DAY_OF_WEEK
doesn't matter, anyway.
那么DAY_OF_WEEK的类型就不重要了。
#1
160
Some of the reasons have already been pointed out. For example, the fact that "...(Almost) All operations on byte, short will promote these primitives to int". However, the obvious next question would be: WHY are these types promoted to int
?
一些原因已经被指出。例如,“……(几乎)所有字节上的操作,short都会将这些原语提升为int”。然而,显而易见的下一个问题是:为什么这些类型被提升为int类型?
So to go one level deeper: The answer may simply be related to the Java Virtual Machine Instruction Set. As summarized in the Table in the Java Virtual Machine Specification, all integral arithmetic operations, like adding, dividing and others, are only available for the type int
and the type long
, and not for the smaller types.
所以去更深一层:答案可能仅仅是相关的Java虚拟机指令集。在总结表中Java虚拟机规范,所有积分运算操作,比如添加、分裂和其他人,只是用于int类型和类型长,而不是为较小的类型。
(An aside: The smaller types (byte
and short
) are basically only intended for arrays. An array like new byte[1000]
will take 1000 bytes, and an array like new int[1000]
will take 4000 bytes)
(顺便说一句:较小的类型(字节和短类型)基本上只用于数组。像new byte[1000]这样的数组需要1000字节,而像new int[1000]这样的数组需要4000字节)
Now, of course, one could say that "...the obvious next question would be: WHY are these instructions only offered for int
(and long
)?".
现在,当然,人们可以说“……”显而易见的下一个问题是:为什么这些指令只针对int(和long)?
One reason is mentioned in the JVM Spec mentioned above:
上面提到的JVM规范中提到了一个原因:
If each typed instruction supported all of the Java Virtual Machine's run-time data types, there would be more instructions than could be represented in a byte
如果每个类型化指令都支持Java虚拟机的所有运行时数据类型,那么将会有比字节中表示的更多的指令
Additionally, the Java Virtual Machine can be considered as an abstraction of a real processor. And introducing dedicated Arithmetic Logic Unit for smaller types would not be worth the effort: It would need additional transistors, but it still could only execute one addition in one clock cycle. The dominant architecture when the JVM was designed was 32bits, just right for a 32bit int
. (The operations that involve a 64bit long
value are implemented as a special case).
此外,可以将Java虚拟机视为一个真实处理器的抽象。为更小的类型引入专门的算术逻辑单元是不值得的:它需要额外的晶体管,但它仍然只能在一个时钟周期中执行一个加法。在设计JVM时,主要的架构是32位的,刚好适合32位的int(涉及64位长值的操作是作为特殊情况实现的)。
(Note: The last paragraph is a bit oversimplified, considering possible vectorization etc., but should give the basic idea without diving too deep into processor design topics)
(注意:考虑到可能的矢量化等因素,最后一段有点过于简化,但是应该给出基本的思想,而不要深入到处理器设计主题)
EDIT: A short addendum, focussing on the example from the question, but in an more general sense: One could also ask whether it would not be beneficial to store fields using the smaller types. For example, one might think that memory could be saved by storing Calendar.DAY_OF_WEEK
as a byte
. But here, the Java Class File Format comes into play: All the Fields in a Class File occupy at least one "slot", which has the size of one int
(32 bits). (The "wide" fields, double
and long
, occupy two slots). So explicitly declaring a field as short
or byte
would not save any memory either.
编辑:一个简短的附录,关注问题中的示例,但从更一般的意义上来说:还可以问,使用较小的类型存储字段是否有益。例如,有人可能认为可以通过存储日历来保存内存。DAY_OF_WEEK字节。但在这里,Java类文件格式发挥了作用:类文件中的所有字段至少占用一个“槽”,其大小为一个int(32位)。(“宽”字段,双长,占用两个槽)。因此显式地将字段声明为短或字节也不会保存任何内存。
#2
37
(Almost) All operations on byte
, short
will promote them to int
, for example, you cannot write:
(几乎所有字节上的操作,short都会将它们提升到int,例如,你不能写:
short x = 1;
short y = 2;
short z = x + y; //error
Arithmetics are easier and straightforward when using int
, no need to cast.
使用int类型时,算术更简单和直接,不需要强制转换。
In terms of space, it makes a very little difference. byte
and short
would complicate things, I don't think this micro optimization worth it since we are talking about a fixed amount of variables.
就空间而言,它没有多大区别。字节和短将使事情变得复杂,我认为这种微观优化不值得,因为我们讨论的是固定数量的变量。
byte
is relevant and useful when you program for embedded devices or dealing with files/networks. Also these primitives are limited, what if the calculations might exceed their limits in the future? Try to think about an extension for Calendar
class that might evolve bigger numbers.
当您为嵌入式设备编程或处理文件/网络时,字节是相关的和有用的。同样,这些原语也是有限的,如果将来的计算可能会超出它们的极限呢?尝试考虑一个日历类的扩展,它可能会进化出更大的数字。
Also note that in a 64-bit processors, locals will be saved in registers and won't use any resources, so using int
, short
and other primitives won't make any difference at all. Moreover, many Java implementations align variables* (and objects).
还要注意,在64位处理器中,局部变量将保存在寄存器中,不会使用任何资源,因此使用int、short和其他原语根本没有什么区别。此外,许多Java实现将变量*(和对象)对齐。
*byte
and short
occupy the same space as int
if they are local variables, class variables or even instance variables. Why? Because in (most) computer systems, variables addresses are aligned, so for example if you use a single byte, you'll actually end up with two bytes - one for the variable itself and another for the padding.
*如果是局部变量、类变量,甚至是实例变量,那么byte和short与int占用相同的空间。为什么?因为在(大多数)计算机系统中,变量地址是对齐的,因此,例如,如果您使用一个字节,那么实际上您将得到两个字节——一个用于变量本身,另一个用于填充。
On the other hand, in arrays, byte
take 1 byte, short
take 2 bytes and int
take four bytes, because in arrays only the start and maybe the end of it has to be aligned. This will make a difference in case you want to use, for example, System.arraycopy()
, then you'll really note a performance difference.
另一方面,在数组中,字节取1个字节,短取2个字节,int取4个字节,因为在数组中,只有开始和结束必须对齐。如果您想要使用System.arraycopy(),那么这将会产生很大的差异,然后您将真正注意到性能的差异。
#3
7
Because arithmetic operations are easier when using integers compared to shorts. Assume that the constants were indeed modeled by short
values. Then you would have to use the API in this manner:
因为与short相比,使用整数更容易进行算术运算。假设这些常量确实是由短值建模的。那么你就必须以这种方式使用API:
short month = Calendar.JUNE;
month = month + (short) 1; // is july
Notice the explicit casting. Short values are implicitly promoted to int
values when they are used in arithmetic operations. (On the operand stack, shorts are even expressed as ints.) This would be quite cumbersome to use which is why int
values are often preferred for constants.
注意到明确的铸件。在算术操作中,短值被隐式地提升为int值。(在操作数堆栈上,short甚至被表示为int。)这将是非常麻烦的使用,这就是为什么int值通常是首选的常量。
Compared to that, the gain in storage efficiency is minimal because there only exists a fixed number of such constants. We are talking about 40 constants. Changing their storage from int
to short
would safe you 40 * 16 bit = 80 byte
. See this answer for further reference.
与之相比,存储效率的提高是最小的,因为只有固定数量的这样的常量。我们讨论的是40个常数。将它们的存储从int改为short将安全的您40 * 16位= 80字节。请参阅此答案以作进一步参考。
#4
5
If you used the philosophy where integral constants are stored in the smallest type that they fit in, then Java would have a serious problem: whenever programmers write code using integral constants, they have to pay careful attention to their code to check if the type of the constants matter, and if so look up the type in the documentation and/or do whatever type conversions are needed.
如果你用哲学,积分常数存储在最小的类型,他们适应,那么Java有一个严重的问题:每当程序员编写代码使用积分常数,他们必须注意他们的代码检查常量的类型,如果是查找文档中的类型和/或做任何类型转换是必要的。
So now that we've outlined a serious problem, what benefits could you hope to achieve with that philosophy? I would be unsurprised if the only runtime-observable effect of that change would be what type you get when you look the constant up via reflection. (and, of course, whatever errors are introduced by lazy/unwitting programmers not correctly accounting for the types of the constants)
既然我们已经勾勒出了一个严重的问题,那么你希望用这种哲学来实现什么好处呢?如果更改的唯一运行时可观察的影响是通过反射查找常量时得到的类型,我不会感到惊讶。(当然,懒惰/不知情的程序员引入的任何错误都不能正确地解释常量的类型)
Weighing the pros and the cons is very easy: it's a bad philosophy.
权衡利弊很容易:这是一种糟糕的哲学。
#5
4
The design complexity of a virtual machine is a function of how many kinds of operations it can perform. It's easier to having four implementations of an instruction like "multiply"--one each for 32-bit integer, 64-bit integer, 32-bit floating-point, and 64-bit floating-point--than to have, in addition to the above, versions for the smaller numerical types as well. A more interesting design question is why there should be four types, rather than fewer (performing all integer computations with 64-bit integers and/or doing all floating-point computations with 64-bit floating-point values). The reason for using 32-bit integers is that Java was expected to run on many platforms where 32-bit types could be acted upon just as quickly as 16-bit or 8-bit types, but operations on 64-bit types would be noticeably slower. Even on platforms where 16-bit types would be faster to work with, the extra cost of working with 32-bit quantities would be offset by the simplicity afforded by only having 32-bit types.
虚拟机的设计复杂性取决于它能执行多少种操作。像“相乘”这样的指令有四种实现——一种是32位整数、64位整数、32位浮点数和64位浮点数——要比除了上面提到的,还有更小的数值类型的版本要容易得多。一个更有趣的设计问题是,为什么应该有四种类型,而不是更少(使用64位整数执行所有整数计算并/或使用64位浮点值执行所有浮点计算)。使用32位整数的原因是,Java被期望在许多平台上运行,在这些平台上,32位类型可以像16位或8位类型一样快速地执行操作,但是对64位类型的操作要明显地慢。即使在使用16位类型更快的平台上,使用32位数量的额外成本也会被只有32位类型的简单性所抵消。
As for performing floating-point computations on 32-bit values, the advantages are a bit less clear. There are some platforms where a computation like float a=b+c+d;
could be performed most quickly by converting all operands to a higher-precision type, adding them, and then converting the result back to a 32-bit floating-point number for storage. There are other platforms where it would be more efficient to perform all computations using 32-bit floating-point values. The creators of Java decided that all platforms should be required to do things the same way, and that they should favor the hardware platforms for which 32-bit floating-point computations are faster than longer ones, even though this severely degraded PC both the speed and precision of floating-point math on a typical PC, as well as on many machines without floating-point units. Note, btw, that depending upon the values of b, c, and d, using higher-precision intermediate computations when computing expressions like the aforementioned float a=b+c+d;
will sometimes yield results which are significantly more accurate than would be achieved of all intermediate operands were computed at float
precision, but will sometimes yield a value which is a tiny bit less accurate. In any case, Sun decided everything should be done the same way, and they opted for using minimal-precision float
values.
对于在32位值上执行浮点计算,优势就不那么明显了。有一些平台,比如浮点a=b+c+d;可以通过将所有操作数转换为更高精度的类型,添加它们,然后将结果转换回32位浮点数进行存储,从而最快地执行。还有其他平台可以更有效地使用32位浮点值执行所有计算。Java决定所有平台的创造者应该需要做同样的方式,他们应该支持32位浮点计算的硬件平台比时间更快,尽管这严重退化的电脑的速度和精度浮点数学在一个典型的电脑,以及许多机器没有浮点单元。请注意,顺便说一下,这取决于b、c和d的值,在计算上述浮点a=b+c+d这样的表达式时,使用更高精度的中间计算;有时会产生比所有中间操作数都要精确得多的结果,这些结果在浮点精度下被计算,但有时会产生一个稍微不那么精确的值。无论如何,Sun决定所有的事情都应该以同样的方式进行,他们选择使用最小精度浮点值。
Note that the primary advantages of smaller data types become apparent when large numbers of them are stored together in an array; even if there were no advantage to having individual variables of types smaller than 64-bits, it's worthwhile to have arrays which can store smaller values more compactly; having a local variable be a byte
rather than an long
saves seven bytes; having an array of 1,000,000 numbers hold each number as a byte
rather than a long
waves 7,000,000 bytes. Since each array type only needs to support a few operations (most notably read one item, store one item, copy a range of items within an array, or copy a range of items from one array to another), the added complexity of having more array types is not as severe as the complexity of having more types of directly-usable discrete numerical values.
请注意,较小数据类型的主要优势在大量存储在数组中时变得很明显;即使拥有小于64位的类型的单个变量没有好处,也值得拥有能够更紧凑地存储较小值的数组;使局部变量为字节而不是长变量可以节省7个字节;拥有1,000,000个数字的数组将每个数字作为一个字节保存,而不是一个7,000,000字节的长波浪。因为每个数组类型只需要支持一些操作(尤其是读一项,存储一个项目,复制数组内的物品,或复制的项目从一个到另一个数组),添加更多的数组类型的复杂性不是那么严重的复杂性有更多类型的直接使用离散的数值。
#6
2
Actually, there'd be a small advantage. If you have a
事实上,有一个小优势。如果你有一个
class MyTimeAndDayOfWeek {
byte dayOfWeek;
byte hour;
byte minute;
byte second;
}
then on a typical JVM it needs as much space as a class containing a single int
. The memory consumption gets rounded to a next multiple of 8 or 16 bytes (IIRC, that's configurable), so the cases when there are real saving are rather rare.
然后在一个典型的JVM上,它需要的空间与一个包含单个int的类一样多,内存消耗被四舍五入到下一个8或16字节的倍数(IIRC,这是可配置的),所以真正的保存是非常罕见的。
This class would be slightly easier to use if the corresponding Calendar
methods returned a byte
. But there are no such Calendar
methods, only get(int)
which must returns an int
because of other fields. Each operation on smaller types promotes to int
, so you need a lot of casting.
如果相应的日历方法返回一个字节,那么这个类会更容易使用。但是没有这样的日历方法,只有get(int),因为其他字段必须返回int。对较小类型的每个操作都提升为int类型,因此需要大量的强制转换。
Most probably, you'll either give up and switch to an int
or write setters like
最可能的情况是,您要么放弃并切换到int类型,要么像这样编写setter
void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
Then the type of DAY_OF_WEEK
doesn't matter, anyway.
那么DAY_OF_WEEK的类型就不重要了。