为什么下面的工作正常?

String str;
while (condition) {
    str = calculateStr();
    .....
}

但是下面这个被认为是危险的/不正确的:

while (condition) {
    String str = calculateStr();
    .....
}

有必要在循环之外声明变量吗?


当前回答

我认为物体的大小也很重要。 在我的一个项目中,我们声明并初始化了一个大型二维数组,该数组使应用程序抛出内存不足异常。 我们将声明移出循环,并在每次迭代开始时清除数组。

其他回答

在while循环之外声明String str允许它在while循环内外被引用。在while循环中声明String str只允许它在while循环中被引用。

在循环中声明将限制各自变量的范围。这完全取决于项目对变量范围的要求。

如果你的calculateStr()方法返回null,然后你试图在str上调用一个方法,你有NullPointerException的风险。

更一般地说,避免使用空值变量。顺便说一下,它对类属性更强。

在这个问题上对几乎所有人的警告:下面是示例代码,在我的Java 7计算机上,循环内部的速度很容易慢200倍(内存消耗也略有不同)。但这不仅关乎范围,还关乎分配。

public class Test
{
    private final static int STUFF_SIZE = 512;
    private final static long LOOP = 10000000l;

    private static class Foo
    {
        private long[] bigStuff = new long[STUFF_SIZE];

        public Foo(long value)
        {
            setValue(value);
        }

        public void setValue(long value)
        {
            // Putting value in a random place.
            bigStuff[(int) (value % STUFF_SIZE)] = value;
        }

        public long getValue()
        {
            // Retrieving whatever value.
            return bigStuff[STUFF_SIZE / 2];
        }
    }

    public static long test1()
    {
        long total = 0;

        for (long i = 0; i < LOOP; i++)
        {
            Foo foo = new Foo(i);
            total += foo.getValue();
        }

        return total;
    }

    public static long test2()
    {
        long total = 0;

        Foo foo = new Foo(0);
        for (long i = 0; i < LOOP; i++)
        {
            foo.setValue(i);
            total += foo.getValue();
        }

        return total;
    }

    public static void main(String[] args)
    {
        long start;

        start = System.currentTimeMillis();
        test1();
        System.out.println(System.currentTimeMillis() - start);

        start = System.currentTimeMillis();
        test2();
        System.out.println(System.currentTimeMillis() - start);
    }
}

结论:根据局部变量的大小,即使变量不是那么大,差异也可能是巨大的。

只是说,有时候,在循环外或循环内确实很重要。

这个问题的一个解决方案是提供一个变量作用域来封装while循环:

{
  // all tmp loop variables here ....
  // ....
  String str;
  while(condition){
      str = calculateStr();
      .....
  }
}

当外部作用域结束时,它们将自动取消引用。