【问题标题】:Why would i+=l compile, where i is int and l is long?为什么 i+=l 会编译,其中 i 是 int 而 l 是 long ?
【发布时间】:2012-02-01 13:25:33
【问题描述】:

我发现了Java's +=, -=, *=, /= compound assignment operators(好问题:)),但它有一部分我不太明白。借用那个问题:

int i = 5;
long l = 8;

那么i = i + l; 将无法编译,但i += l; 将正常编译。

对链接问题的接受回答指出:

E1 op= E2 形式的复合赋值表达式等价于 E1 = (T)((E1) op (E2)),其中 T 是 E1 的类型,除了 E1 只计算一次。

这使得i += l;i = (int)((i) + (l)); 相同,但i 仅被评估一次。

long 可能(IIRC 甚至可以保证)比int 长,因此可以容纳更大范围的值。

鉴于这种情况很容易由于在语句执行期间的某个时间点(右值表达式评估或赋值)进行必要的缩小转换而导致数据丢失,为什么i += l; 不是编译时错误或至少是警告?

【问题讨论】:

  • 那个问题完全一样,也回答了。 (即,这是因为 i += l; 进行了强制转换,如果 i 的类型是 int,则它与 i = (int)(i + l); 相同。
  • 您对所链接问题的答案究竟有哪些不明白的地方?它的要求几乎完全相同,并且您需要的信息都应该在那里 - 如果您仍然无法理解它,您必须更具体!
  • @nos 是对的。您不是在询问问题的一部分,而是在完全复制它。如果您已经阅读了该问题和答案,也许您可​​以解释一下您对给出的(高度投票的)答案的不理解。
  • Java += operator的可能重复
  • @nos,我猜 OP 的重点是这种隐式缩小转换可能会导致数据丢失,编译器可以(应该)至少对此发出警告。

标签: java variable-assignment compound-operator


【解决方案1】:

基本上,因为i += l 的编译就像写成i = (int) (i + l) 一样。将int 值添加到bytechar 变量时也会出现类似的“惊喜”——赋值运算符有效,而普通加法运算符无效。

【讨论】:

  • 这已在上述问题的已接受答案中进行了解释。我想 OP 的重点是这种隐式缩小转换可能会导致数据丢失,编译器可以(应该)至少对此发出警告。
  • 所以,除非我遗漏了什么,Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. 的哪一部分说应该进行隐式向下转换,而没有任何迹象表明这样做了?还是那是别的地方?如果是后者,我认为其他问题的答案不一定适用。
【解决方案2】:

鉴于这种情况很容易由于在语句执行期间的某个点(右值表达式评估或赋值)进行必要的窄化转换而导致数据丢失,为什么 i += l;不是编译时错误或至少是警告?

正如您所说,它可能应该是编译时错误或至少是警告。我知道的大多数书籍和教程都将x += y; 介绍为x = x + y; 的简写。老实说,除了一个之外,我不知道有什么可以区分 JLS 的 15.26.2 Compound Assignment Operators 部分。

Java Puzzlers: Traps, Pitfalls, and Corner Cases 的第 2 章(谜题 9)中,作者(Joshua Bloch 和 Neal Gafter)要求您提供 xi 的声明,这样这是一个法律声明:

x += i;

这不是:

x = x + i;

有很多解决方案,包括您在问题中发布的前两行代码。作者警告不要对 byteshortchar 类型的变量使用复合赋值运算符,并建议在对 int 类型的变量使用这些运算符时,应确保 RHS 表达式不是longfloatdouble

他们以以下观察结束(强调我的):

总而言之,复合赋值运算符会默默地生成强制转换。如果计算结果的类型比变量的类型宽,则生成的类型转换是危险的窄化类型转换。这样的强制转换可以默默地丢弃精度或量级。 对于语言设计者来说,复合赋值运算符生成隐形强制转换可能是一个错误;变量的类型比计算结果窄的复合赋值可能是非法的。

【讨论】:

    【解决方案3】:

    这样做的原因是你可以这样做:

    byte b = 1;
    
    b += 1;
    

    如果 += 扩展为 b = b + 1,则表达式不会进行类型检查,因为表达式“b + 1”是 int 类型。 java中的所有整型表达式至少都是int类型,即使你把两个字节加在一起。

    public class Test {
      public static void main(String[] args) {
        byte b = 1;
        byte c = 2;
        byte d = b + c;
      }
    }
    
    
    Test.java:5: possible loss of precision
    found   : int
    required: byte
        byte d = b + c;
                   ^
    1 error
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-25
      • 1970-01-01
      • 2019-12-05
      • 2010-10-05
      • 2011-10-05
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      相关资源
      最近更新 更多