【问题标题】:Is a variable declared inside a loop limited in scope by a single iteration?在循环内声明的变量是否受单次迭代的范围限制?
【发布时间】:2015-03-26 13:25:28
【问题描述】:

我知道这听起来微不足道,但我只是想清醒一下..

考虑

for (int i = 0; i < 100; i++) {
    int x=i;
    System.println(i);
}

是为每次迭代创建和分配的新 int 内存,还是编译器巧妙地推断场景并只创建一次并更改其值(因为它知道这是一个循环),

而就方法签名中i的声明而言,显然只创建了一次吧?

也会

int x = 0;

for (int i = 0; i < 100; i++) {
    x = i;
    System.println(i);
}

真的比上面那个更有效率吗?

在java中,如果我不需要在循环外访问x,最好在循环内声明它,这是一个好习惯吗?

【问题讨论】:

  • 最终这无关紧要。 JIT 将为您提供帮助,因此这两个版本最终将是等效的。至于什么是好的做法,我更喜欢你的第二种做事方式,而许多其他人更喜欢第一种......因此,这是个人喜好/口味/编码限制的问题。按此顺序。
  • 不要再担心像这样的“优化”了。你的瓶颈在另一座城堡。
  • 好吧,不要怀疑,做你觉得最舒服的事;这就是你对代码保持信心的方式,对吧?此外,如果您在循环中声明它,您将无法在它之外访问它。因此,这取决于您是否真的需要在循环之外访问它。是的,JIT 也可以检测到这一点。
  • 正如安德森 (Matrix) 先生所说:“永远不要派人去做机器的工作”。 Java JIT 肯定会处理这种情况,并将变量放在寄存器中。

标签: java performance loops scope declaration


【解决方案1】:

您可以比较两种情况下创建的字节码。

在循环外声明变量:

public static void main(String[] args) {
    int x;
    for (int i = 0; i < 100; i++) {
        x = i;
    }
}

结果:

public static void main(java.lang.String[]);
Code:
   0: iconst_0
   1: istore_2
   2: iload_2
   3: bipush        100
   5: if_icmpge     16
   8: iload_2
   9: istore_1
  10: iinc          2, 1
  13: goto          2
  16: return

在循环内声明变量时:

public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
        int x = i;
    }
}

给予:

public static void main(java.lang.String[]);
Code:
   0: iconst_0
   1: istore_1
   2: iload_1
   3: bipush        100
   5: if_icmpge     16
   8: iload_1
   9: istore_2
  10: iinc          1, 1
  13: goto          2
  16: return

如您所见,字节码几乎完全相同。唯一的区别是,在第一种情况下,x 是变量 1,i 是变量 2,而在第二种情况下,x 是 2,i 是 1。因此,关于性能,两个代码是等效的.

现在,关于设计,最好尽可能限制变量的范围。所以在循环内声明x 可能会更好。

【讨论】:

  • "关于设计,最好总是尽可能地限制变量的范围"
  • 如果你每次迭代都重用相同的值,我同意你的看法。也许我的断言在这里有点强。但不可否认,限制变量的范围是一种行之有效的做法。许多书籍都推荐它,例如 Code Complete 和 Effective Java,其中有专门的部分(第 45 条:最小化局部变量的范围)。
  • 是的,我的书架上也有 Effective Java ;)(虽然不是 Code Complete)。实际上,这是在循环的每次迭代中重用变量的范围内。 个人,在这种情况下,我发现将它们声明在循环之外而不是在循环中更清楚。也许我的旧 C 习惯妨碍了这里,我不知道......
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 2018-04-07
  • 2015-11-29
  • 1970-01-01
  • 2012-07-23
  • 2022-11-04
  • 2011-02-13
  • 1970-01-01
相关资源
最近更新 更多