Java 在循环之前或循环中声明变量之间的区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/407255/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:16:06  来源:igfitidea点击:

Difference between declaring variables before or in loop?

javaperformanceloopsvariablesinitialization

提问by Rabarberski

I have always wondered if, in general, declaring a throw-away variable before a loop, as opposed to repeatedly inside the loop, makes any (performance) difference? A (quite pointless)example in Java:

我一直想知道,一般来说,在循环之前声明一个丢弃变量,而不是在循环内重复,是否会产生任何(性能)​​差异?一(毫无意义),例如在Java中:

a)declaration before loop:

a)循环前声明:

double intermediateResult;
for(int i=0; i < 1000; i++){
    intermediateResult = i;
    System.out.println(intermediateResult);
}

b)declaration (repeatedly) inside loop:

b)在循环内声明(重复):

for(int i=0; i < 1000; i++){
    double intermediateResult = i;
    System.out.println(intermediateResult);
}

Which one is better, aor b?

哪个更好,ab

I suspect that repeated variable declaration (example b) creates more overhead in theory, but that compilers are smart enough so that it doesn't matter. Example bhas the advantage of being more compact and limiting the scope of the variable to where it is used. Still, I tend to code according example a.

我怀疑重复的变量声明(例如b理论上会产生更多的开销,但编译器足够聪明,所以这无关紧要。示例b的优点是更紧凑,并将变量的范围限制在使用它的地方。尽管如此,我还是倾向于根据示例a进行编码。

Edit:I am especially interested in the Java case.

编辑:我对 Java 案例特别感兴趣。

采纳答案by Daniel Earwicker

Which is better, aor b?

ab哪个更好?

From a performance perspective, you'd have to measure it. (And in my opinion, if you can measure a difference, the compiler isn't very good).

从性能的角度来看,您必须对其进行衡量。(在我看来,如果您可以衡量差异,则编译器不是很好)。

From a maintenance perspective, bis better. Declare and initialize variables in the same place, in the narrowest scope possible. Don't leave a gaping hole between the declaration and the initialization, and don't pollute namespaces you don't need to.

从维护的角度来看,b更好。在尽可能最窄的范围内,在同一个地方声明和初始化变量。不要在声明和初始化之间留下空白,也不要污染不需要的命名空间。

回答by SquidScareMe

I think it depends on the compiler and is hard to give a general answer.

我认为这取决于编译器,很难给出一般性答案。

回答by annakata

It is language dependent - IIRC C# optimises this, so there isn't any difference, but JavaScript (for example) will do the whole memory allocation shebang each time.

它依赖于语言 - IIRC C# 对此进行了优化,因此没有任何区别,但是 JavaScript(例如)每次都会进行整个内存分配。

回答by Abgan

Even if I know my compiler is smart enough, I won't like to rely on it, and will use the a) variant.

即使我知道我的编译器足够聪明,我也不喜欢依赖它,而是使用 a) 变体。

The b) variant makes sense to me only if you desperately need to make the intermediateResultunavailable after the loop body. But I can't imagine such desperate situation, anyway....

只有当您迫切需要在循环体之后使中间结果不可用时,b) 变体才对我有意义。但无论如何,我无法想象这种绝望的情况......

EDIT: Jon Skeetmade a very good point, showing that variable declaration inside a loop can make an actual semantic difference.

编辑:Jon Skeet提出了一个很好的观点,表明循环内的变量声明可以产生实际的语义差异。

回答by Stew S

I suspect a few compilers could optimize both to be the same code, but certainly not all. So I'd say you're better off with the former. The only reason for the latter is if you want to ensure that the declared variable is used onlywithin your loop.

我怀疑一些编译器可以将两者优化为相同的代码,但肯定不是全部。所以我会说你最好选择前者。后者的唯一原因是如果您想确保声明的变量在您的循环中使用。

回答by Chris

As a general rule, I declare my variables in the inner-most possible scope. So, if you're not using intermediateResult outside of the loop, then I'd go with B.

作为一般规则,我在最内部的可能范围内声明我的变量。因此,如果您不在循环之外使用中间结果,那么我会选择 B。

回答by Jon Skeet

It depends on the language and the exact use. For instance, in C# 1 it made no difference. In C# 2, if the local variable is captured by an anonymous method (or lambda expression in C# 3) it can make a very signficant difference.

这取决于语言和确切用途。例如,在 C# 1 中它没有区别。在 C# 2 中,如果局部变量被匿名方法(或 C# 3 中的 lambda 表达式)捕获,它会产生非常显着的差异。

Example:

例子:

using System;
using System.Collections.Generic;

class Test
{
    static void Main()
    {
        List<Action> actions = new List<Action>();

        int outer;
        for (int i=0; i < 10; i++)
        {
            outer = i;
            int inner = i;
            actions.Add(() => Console.WriteLine("Inner={0}, Outer={1}", inner, outer));
        }

        foreach (Action action in actions)
        {
            action();
        }
    }
}

Output:

输出:

Inner=0, Outer=9
Inner=1, Outer=9
Inner=2, Outer=9
Inner=3, Outer=9
Inner=4, Outer=9
Inner=5, Outer=9
Inner=6, Outer=9
Inner=7, Outer=9
Inner=8, Outer=9
Inner=9, Outer=9

The difference is that all of the actions capture the same outervariable, but each has its own separate innervariable.

不同之处在于所有动作都捕获相同的outer变量,但每个动作都有自己独立的inner变量。

回答by Powerlord

In my opinion, b is the better structure. In a, the last value of intermediateResult sticks around after your loop is finished.

在我看来, b 是更好的结构。在 a 中,intermediateResult 的最后一个值在循环完成后仍然存在。

Edit: This doesn't make a lot of difference with value types, but reference types can be somewhat weighty. Personally, I like variables to be dereferenced as soon as possible for cleanup, and b does that for you,

编辑:这与值类型没有太大区别,但引用类型可能有些重要。就个人而言,我喜欢尽快取消引用变量以进行清理,而 b 会为您做到这一点,

回答by Triptych

I would always use A (rather than relying on the compiler) and might also rewrite to:

我会一直使用 A(而不是依赖编译器),也可能会重写为:

for(int i=0, double intermediateResult=0; i<1000; i++){
    intermediateResult = i;
    System.out.println(intermediateResult);
}

This still restricts intermediateResultto the loop's scope, but doesn't redeclare during each iteration.

这仍然限制intermediateResult在循环的范围内,但不会在每次迭代期间重新声明。

回答by Michael Haren

This is a gotcha in VB.NET. The Visual Basic result won't reinitialize the variable in this example:

这是 VB.NET 中的一个问题。Visual Basic 结果不会重新初始化此示例中的变量:

For i as Integer = 1 to 100
    Dim j as Integer
    Console.WriteLine(j)
    j = i
Next

' Output: 0 1 2 3 4...

This will print 0 the first time (Visual Basic variables have default values when declared!) but ieach time after that.

这将在第一次打印 0(Visual Basic 变量在声明时具有默认值!)但之后i每次都打印。

If you add a = 0, though, you get what you might expect:

= 0但是,如果您添加一个,您会得到您所期望的:

For i as Integer = 1 to 100
    Dim j as Integer = 0
    Console.WriteLine(j)
    j = i
Next

'Output: 0 0 0 0 0...