【问题标题】:Difference between a += 10 and a = a + 10 in java? [duplicate]java中a + = 10和a = a + 10之间的区别? [复制]
【发布时间】:2011-01-06 02:51:01
【问题描述】:

a += 10a = a + 10 是否相同,或者它们之间有什么区别?我在学习 Java 作业时遇到了这个问题。

【问题讨论】:

  • 这个问题重复的问题是在这个问题之后发布的,所以不应该是这个问题的重复吗?
  • @Kröw 不,这并不重要。参见例如meta.stackoverflow.com/q/251938/2891664

标签: java variable-assignment


【解决方案1】:

S/W领域有一些术语,我可以给你解释一下,

a=a+1 中,a 的赋值是在两步之后测量的

  1. 系统计算 a 的值(在此处创建一个新的独立副本)
  2. 系统将隔离变量a加10,然后将隔离a的值分配给左侧a

但在第二种情况下,

  1. 系统知道a的值,直接给a加10(这里没有做隔离副本)。

希望这对您有所帮助,还有一件事,我们通常使用a += 10;的方法,因为它可以降低运营成本,就像其他人一样,

【讨论】:

    【解决方案2】:

    正如您现在提到的铸造......在这种情况下有所不同:

    byte a = 5;
    a += 10; // Valid
    a = a + 10; // Invalid, as the expression "a + 10" is of type int
    

    来自 Java 语言规范section 15.26.2

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

    有趣的是,他们在规范中给出的示例:

    short x = 3;
    x += 4.6;
    

    在 Java 中有效,但在 C# 中不是...基本上在 C# 中,编译器执行 += 和 -= 的特殊情况,以确保表达式是目标类型或者是目标类型范围内的文字。

    【讨论】:

    【解决方案3】:

    没有区别,一个是另一个的简写。甚至编译器也会为两者生成相同的指令。

    编辑:编译器不会为两者生成相同的代码,正如我刚刚发现的那样。看看这个:

    dan$ cat Test.java
    public class Test {
        public static void main(String[] args) {
            int a = 0;
            a = a + 10;
            a += 20;
        }
    }
    
    dan$ javap -c Test
    Compiled from "Test.java"
    public class Test extends java.lang.Object{
    public Test();
      Code:
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   return
    
    public static void main(java.lang.String[]);
      Code:
       0:   iconst_0
       1:   istore_1
       2:   iload_1
       3:   bipush  10
       5:   iadd
       6:   istore_1
       7:   iinc    1, 20
       10:  return
    
    }
    

    因此,简短的回答是,特别是对于 Java 初学者或任何不担心在最小级别进行优化的人来说,它们是可以互换的。长答案将取决于我阅读有关 iadd 与 iinc 的内容。

    编辑 2:好的,我回来了。指令规格(大致)如下:

    iadd - 添加栈顶的两个整数

    iinc - 将局部变量增加一个常量

    正如我们在上面看到的,我们可以使用 iinc 保存一些指令,只要右侧有一个常量。

    但是如果我们有会发生什么

    a += a?

    那么代码如下所示:

       7:   iload_1
       8:   iload_1
       9:   iadd
       10:  istore_1
    

    如果我们有a = a + a,我们会得到同样的结果。

    【讨论】:

    • 我知道这一点。但我读到有一些与铸造有关的差异。我不明白,所以在这里要求了解更多。
    • 你应该在 topicstart 中说清楚。
    • @danben:很高兴看到编辑(因为编译器不会生成相同的代码)。但是一旦启用了 JIT 的 JVM(如 HotSpot)开始使用它,我怀疑如果表达式没有其他影响,即使是较长的形式也会针对增量操作进行优化。
    • 嘿,你在哪里编译Test.java? :)
    • @Pascal Thivent:为了简洁起见,我把它省略了。
    【解决方案4】:

    这是在Java Language Specification, section 15.25.2 中定义的。重点是:

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

    也就是说,在您的情况下,区别在于隐式类型转换:

    byte a = 100;
    a += 1000;    // compiles
    a = a + 1000; // doesn't compile, because an int cannot be assigned to a byte.
    

    【讨论】:

    • byte a = 100;a += 1000; 分配给 a 的值是多少?
    • 1100 二进制表示的 8 个最低有效位,就像将 int 强制转换为字节一样。
    【解决方案5】:

    在您显示的表达式中,它们是等价的,在如下表达式中:

    array[getIndex(context)][some / complex + expression] += offset;
    

    您会知道 += 运算符(和其他赋值运算符)在哪些情况下有用。如果表达式不平凡,则 += 运算符可以防止错误并提高可读性,从而提高可维护性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-05
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-11
      • 2016-05-04
      • 1970-01-01
      相关资源
      最近更新 更多