使用循环确定变量范围

时间:2014-02-27 18:42:42

标签: java while-loop garbage-collection scope

今天我们在工作中进行了讨论,这两个函数的性能更高,内存消耗更少,并且不会对gc造成压力。

public class Main {

    public void do1() {
        int result = 0;
        int val;
        do {
            val = calc(result);
            result = val * 2;
        } while (result < 1000);
    }

    public void do2() {
        int result = 0;
        do {
            final int val = calc(result);
            result = val * 2;
        } while (result < 1000);
    }

    private int calc(final int i) {
        return i + 2;
    }
}

在我看来两者都是等价的,如果在循环内部或外部定义 val 并不重要。我脑海中唯一想到的是变量范围应尽可能缩小。但是,我们讨论gc如何处理这些情况并且我们没有找到解决方案。

我们查看了字节码并没有区别

Compiled from "Main.java"
public class Main {
  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void do1();
    Code:
       0: iconst_0
       1: istore_1
       2: aload_0
       3: iload_1
       4: invokespecial #2                  // Method calc:(I)I
       7: istore_2
       8: iload_2
       9: iconst_2
      10: imul
      11: istore_1
      12: iload_1
      13: sipush        1000
      16: if_icmplt     2
      19: return

  public void do2();
    Code:
       0: iconst_0
       1: istore_1
       2: aload_0
       3: iload_1
       4: invokespecial #2                  // Method calc:(I)I
       7: istore_2
       8: iload_2
       9: iconst_2
      10: imul
      11: istore_1
      12: iload_1
      13: sipush        1000
      16: if_icmplt     2
      19: return
}

有人知道这里是否真的没有区别或能否解决讨论?

2 个答案:

答案 0 :(得分:2)

正如您在检查字节码时看到的那样,Java没有区别。您可能会在其他语言中看到一些差异,例如,如果在C中编写相同的代码。

所以在你的情况下,论证是关于化妆品和可维护性。

我认为使用最具体的范围界定 - 如do2 - 更好,因为:

  • 它改善了所需变量的位置,
  • 它使重构时代码块的提取更容易,
  • 对于一个更复杂的例子确实会产生不同字节码的情况,并且在循环中分配变量的成本并不太高(例如,对于大型复合对象,你可能不想这样做),这是一个好习惯。

不同点,但在您的示例中,我甚至认为您可以在下一个表达式中内联val变量。不这样做只会增加噪音。但我认为这样做是为了示例或打印出值。

答案 1 :(得分:-1)

没有区别。由于没有分配new个对象,因此这些都没有与垃圾收集器进行任何交互。 int变量在堆栈上分配。

这反映在每个相同的字节码中。