为什么 byte += 1 可以编译通过,但 byte = byte + 1 却不行?

22

如果我有一个字节变量:byte b = 0;

为什么下面的代码能够正常工作:

   b++;
   b += 1; // compiles

...但这并没有?

   b = b + 1; // compile error

编译器是否将第一个解释为byte,第二个解释为int

[编辑]

我知道类型转换,但我想引起您对b ++,b + = 1和b = b + 1的注意。

我认为它们相等,那么为什么编译器会将它们区分开来?它们之间有什么区别?

  b += 1 and b = b + 1 ?

https://dev59.com/3nVD5IYBdhLWcg3wHnyd 有你需要的答案。 - pyvi
1
不要小看这个:)+运算符实际上确保整数部分。 - bestsss
1
对于编辑部分:byte b=0; b+=333; 这是可以的。b+=1 编译时会像 b=(byte)(b+1) 一样。 - bestsss
8个回答

28

有没有一种方法可以编写数字常量,以便将其视为字节?如果我写7F,则会将其视为浮点数,7L是长整型等等。那么像7B这样的东西会被视为字节吗? - BigMac66
@BigMac66,static final byte C1 = 11;// this is a byte 但是 C1+C1 仍然不是一个byte,然而 static final byte C2 = C1 + C1; 是正确的(因为它是由编译器计算而不是运行时),从C1中去掉final会导致错误。 - bestsss
我知道这一点,我的问题是当您编写一个原始常量值时,您可以附加一个字母来指定您打算使该常量成为的类型,那么对于字节原语是否有一个字母?到目前为止,我只能找到 L(长整型)、D(双精度浮点型)和 F(浮点型) - 还有其他的吗? - BigMac66
1
@BigMac66:没有其他后缀,也许并不需要它们,因为在必要时,类型为“int”的编译时常量可以隐式地转换为较窄的类型。 - axtavt

3
可能会出现精度丢失的问题。将其转换类型后,问题就解决了。
b = (byte) (b + 1);

答案是正确的,但我仍然不喜欢这个解释。如果可能的精度损失在这里是一个有效的理由,那么对于整数也应该被禁止。毕竟,Integer.MAX_VALUE + 1也有相同(或类似)的问题。 - Konrad Rudolph
你是对的。编译器在字节和整数方面保护得更好:b = 127; 对于编译器来说是可以的,而 b = 128; 不行,必须在赋值之前进行强制转换,否则会得到一个正确的 -128 值。整数则不然。另一方面,你可以说 int i = 2147483647; 这是 Integer.MAX_VALUE,如果你再加一 int i = 2147483648; 就会得到一个编译器错误“整数过大”。我认为 axtavt 解释得很好。对于字节,我们有一个提升,但对于整数则没有。 - Costis Aivalis

2

在Java中,整数的默认类型是int,浮点数的默认类型是double。因此,默认情况下将b转换为整数以执行操作。因此,为了防止可能的精度损失,在存储结果之前需要进行类型转换。但是b+=1会自动完成这个过程。


2
是的,+ 操作的结果是 int 类型,因此需要进行类型转换才能将其赋值给 byte 变量。

1

类型为byte和short的操作数在被传递给运算符之前会自动提升为int类型。

因此,当您执行byte b = b + 1;时,它将其视为"int",因为对byte值执行了操作。所以为了避免这种情况,我们使用b+=1;,这里会自动转换为byte类型。


0

你需要将其转换为字节:

b = (byte) (b + 1);

我知道强制类型转换可以解决这个问题,但我想学习编辑部分中写的其他东西。 - user467871

0

执行 b + 1 会将结果扩展为整数,将其赋值回字节 b 会导致精度损失。解释:转换和提升。但我更喜欢 axtavt 的答案。


0

我不认同关于精度损失的论点,因为编译器在处理整型和长整型时也不会以类似的方式保护你。 我认为真正的答案在于JLS对整型比字节有更好的支持,正如这个回答所述: https://dev59.com/tWkw5IYBdhLWcg3wi7Jz#13211737


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接