【问题标题】:java best practices using += operator使用 += 运算符的 java 最佳实践
【发布时间】:2015-07-02 01:20:45
【问题描述】:

我正在阅读一本“Java 8 基础知识入门”一书。我看到了这一行:

//some code...
sum = sum + i; // Better to use sum += i
//more code...

那么我的疑问是:这是真的吗?为什么使用+= 运算符更好?我以为+= 运算符只是一个更简化的表达式?如果我使用其中一种或另一种,代码性能会受到哪些影响?

【问题讨论】:

  • 是的,我只是想,但是是正确的,最后最好使用+=。谢谢@Trobbins
  • @Trobbins 这在某种程度上正好相反。使用a = a + ba += b 更安全。无论如何,我认为它更短,因为它更短。
  • 回答您问题的另一部分:在指令级别的性能方面,sum += i 优于 sum = sum + i
  • @I.K.我不这么认为。它们之间不会有任何性能差异。
  • sum += i 表示您对 sum 类型进行了隐式转换。这也可以看作是一个缺点。一般来说,隐藏类型的会话可能很危险,因为您不会立即看到它正在发生。

标签: java performance syntax operators bytecode


【解决方案1】:

我认为,这本书提供了使用+= 作为最佳实践。确实sum += isum = sum + i这2条语句没有区别

我实现了 2 个类,每个类都包含一个语句,并使用命令 javap 观察字节码

这是程序 1:

public class Program1 {
     public static void main(String []args) {
        int i = 1;
        int sum = 2;
        sum += i;
     }
}

这是字节码:

public class Program1 {
  public Program1();
    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_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: istore_1
       8: return
}

这是程序 2:

public class Program2 {
    public static void main(String []args) {
        int i = 1;
        int sum = 2;
        sum = sum + i;
    }
}

这是字节码:

public class Program2 {
  public Program2();
    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_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: iadd
       7: istore_1
       8: return
}

如上所见,字节码是一样的,所以语句是一样的。没有区别。

编辑 1:如何运行 javap 命令

  1. 将 Program1.java 保存到 java 文件中
  2. 编译代码。运行javac Program1.java
  3. Program1 和 Program2 都应该编译成功。
  4. 运行javap -c Program1.class 以查看字节码。

编辑2:变量类型不同时运算符之间的区别

+= 运算符隐式转换为左运算符,因此如果变量的类型不同,+= 运算符将自动转换。

这里是代码

long i = 1;
int sum = 2;
sum += i; //means sum = (int)(i + sum)

此外,sum = sum + i 没有隐式转换,此语句将无法编译。

如果需要强制转换,我通常使用显式强制转换。这使代码更具可读性和安全性。

【讨论】:

  • 我复制并得到了相同的结果。虽然我们不太确定为什么这本书说最好使用简洁的语法。 OP从未说明这本书的原因。
  • 非常有趣。对 int i 和 double sum 做同样的事情,还是一样吗?或 double i 和 int sum,你应该看到区别
  • 请在您的第二句中添加“ 假设两者都编译 ”,否则是错误的(参见 ericbn 的回答)。
  • 我不打算编译。我已经编译了这两个文件。查看我的编辑。 @maaartinus
  • 两种类型相同,你是对的。但是对于double i = 1; int sum = 2;,表达式sum = sum + i 错过了一个演员表。
【解决方案2】:

没有性能差异。一种方式可能会更好读一些。

可以说sum += i; 是更好的风格,因为它不是多余的,读者可能需要稍微少一点的工作来弄清楚+= 发生了什么,因为没有必要在两边都寻找 sum赋值运算符。

“最佳实践”在可读性和可维护性方面的存在至少与对性能的关注一样多,不要假设一切都与性能有关。

在一些涉及隐式转换的晦涩情况下使用+= 可能会出现问题。有一个 Java 谜题者(来自 Bloch 和 Gafter 书中)设法滥用了这个,see this question

【讨论】:

    【解决方案3】:

    正如@Trinimon 评论的那样,+=+ 运算符之间存在区别:

    E1 op= E2 等价于E1 = (T) ((E1) op (E2)),其中TE1 的类型,但E1 只计算一次。 (§15.26.2 Compound Assignment Operators)

    所以

    int sum = 0;
    sum += 1.0; // this is equivalent to sum = (int) (sum + 1.0);
    sum = sum + 1.0; // this will not compile
                     // incompatible types: possible lossy conversion from double to int
    

    与常识相反,使用+= 运算符更安全。

    好问题!

    参考

    Java's +=, -=, *=, /= compound assignment operators

    【讨论】:

    • OP 不要求在 += 运算符中进行隐式转换,因为我们可以假设问题中的语句将编译。我们可以假设两个变量具有相同的类型。不过,你的回答注意了一个好点。
    • @erencan,他在问“为什么使用+= 运算符更好?”我指出了不同之处。如果我们“假设两个变量具有相同的类型”,那么使用+(而不是+=)运算符将保证假设是正确的(而使用+= 则不会)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-11
    • 2012-08-04
    • 2020-03-22
    • 2010-09-08
    • 2015-03-18
    • 2013-05-27
    相关资源
    最近更新 更多