为什么是“ int i = 2147483647 +1;” 可以,但是“字节b = 127 + 1;” 不可以编译吗?


126

为什么int i = 2147483647 + 1;可以,但byte b = 127 + 1;不能编译?


16
我也有一个真正的疑问:为什么byte数据类型这么痛苦?
BoltClock

9
这绝对byte是签名而不是未签名的设计错误。
无可争议的2011年

4
@BoltClock如果您不知道如何正确使用它,那只会很痛苦。stackoverflow.com/questions/397867/...
starblue

2
@starblue,是否有实际的示例适用于Java字节类型?
托尔比约恩Ravn的安徒生

如果有指定为字节的数据,请使用Java byte来简化说明,例如在参数中。在这种情况下,您无法分配int值的事实甚至会引起一些错误。或用于byte节省阵列空间。我不会使用byte恰好适合一个字节的单个值。
starblue 2011年

Answers:


172

常量被评估为int,因此会2147483647 + 1溢出并为您提供一个新的int,该int可分配给int,同时127 + 1也被评估为intequals 128,而不能分配给byte


10
实际上,今天,我读了一些Java难题器,包括一个与此有关的难题...参见这里:javapuzzlers.com/java-puzzlers-sampler.pdf-难题3
MByD 2011年

3
问题是int归因于二进制数值提升的类型,值127是红色鲱鱼。
starblue 2011年

我希望常数以无穷的精度求值,并且还会给出int i = 2147483647 + 1的错误;
爱德华多

@MByD:正如您所说的“ while 127 + 1 also evaluated as int equals to 128, and it is not assignable to byte.”,这是否意味着50 + 1将被评估为byte并因此可分配给byte
虎山

1
@ 10101010-不完全是。它可以分配给字节,但是首先(根据标准)它将被评估为int。
MByD 2011年

35

文字127表示类型为int的值。文字1也是如此。这两个的总和是整数128。在第二种情况下,问题是您将其分配给类型为byte的变量。它与表达式的实际值无关。它与Java不支持强制(*)有关。您必须添加类型转换

byte b = (byte)(127 + 1);

然后编译。

(*)至少不是String-to-integer,float-to-Time等类型的Java。如果在某种意义上说是强制性的,则Java确实支持强制性(Java将其称为“扩大”)。

不,“胁迫”一词不需要纠正。为此,它是经过精心设计和正确选择的。从最近的资料来源(维基百科):“在大多数语言中,无论是在编译期间还是在运行期间,胁迫一词都用于表示隐式转换。” 在计算机科学中,类型转换,类型转换和强制转换是将一种数据类型的实体隐式或隐式更改为另一种数据类型的不同方式。”


您的代码示例可能应该是字节b =(字节)127 + 1; 这是“将1最大化字节值加1”,您的示例只是将int值128转换为字节值。
NKCSS 2011年

6
@NKCSS-我认为您不对,这- (byte)(127 + 1)将128(整数)转换为一个字节,而(byte)127 + 1将127转换为一个字节,但随后又转换为一个int,因为它已添加到1(int)中,因此您得到128(int)并且错误仍然存​​在。
MByD 2011年

6

作为@MByD的证据:

以下代码编译:

byte c = (byte)(127 + 1);

因为尽管expression (127 + 1)是int并且超出了off byte类型的范围,但结果将强制转换为byte。此表达式产生-128


3

JLS3#5.2分配转换

(变量=表达式)

另外,如果该表达式是类型为byte,short,char或int的常量表达式(第15.28节):

如果变量的类型为byte,short或char,并且常量表达式的值可表示为变量的类型,则可以使用缩窄的原始转换。


没有这个子句,我们将无法编写

byte x = 0;
char c = 0;

但是我们应该能够做到这一点吗?我不这么认为。在原语之间进行转换时,发生了很多魔术,必须非常小心。我会尽力写作

byte x = (byte)0;

关于我们应该能够解决的问题……我没有发现任何真正的问题,byte x = 0但是我还是一个C程序员。
Grady Player

我也许可以看到反对char c = 0的参数,但是为什么字节x = 0错误呢?
Michael Burge

这会误导未经训练的眼睛,以为他们将字节0分配给字节变量。在此示例中,危害不大,但通常,由于隐式转换,对byte / short / char进行操作可能会非常混乱。它们比人们想象的要复杂得多。我想在代码中尽可能地清晰,不要为了节省一些关键而引入任何不确定性。
无可争议的2011年

当缩小原语的转换是从long到int时,例如int i = 1 + 0L,是否适用类似的规则?只是问一下,因为您引用的文字明确地省略了这种情况。
Erwin Smout 2011年

@Erwin不,这int i=0L是非法的。
无可辩驳的2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.