creating final variables inside a loop

2020-01-26 07:20发布

is this allowed in java:

for(int i=0;i<5;i++){
  final int myFinalVariable = i;
}

The keyword of my question is final. Is it allowed to do a final variable that changes with every run of the loop? I was wondering this because final says that you can't change the value of the variable (calling only myFinalVariable = i), but i'm redefining the whole variable with final int.

Are they two completely different variables just with the same name - with the variable from the previous run of the loop already heading down the road to the garbage collector?

标签: java final
5条回答
Summer. ? 凉城
2楼-- · 2020-01-26 07:34

As answered, Yes, you may indeed mark the variables in a loop as 'final'. Here is the effect of doing so (Java 7, Eclipse Indigo, Mac OS X Lion).

for ( int i = 0; i < 5; i++ ) {

  // With 'final' you cannot assign a new value.
  final int myFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myFinalVariable = 7; // Compiler error: The final local variable myFinalVariable cannot be assigned.

  // Without 'final' you can assign a new value.
  int myNotFinalVariable = i;  // Gets 0, 1, 2, 3, or 4 on each iteration.
  myNotFinalVariable = 7; // Compiler is OK with re-assignment of variable's value.

}
查看更多
唯我独甜
3楼-- · 2020-01-26 07:35

Yes, it is allowed. The final keyword means that you can't change the value of the variable within its scope. For your loop example, you can think of the variable going out of scope at the bottom of the loop, then coming back into scope with a new value at the top of the loop. Assigning to the variable within the loop won't work.

查看更多
老娘就宠你
4楼-- · 2020-01-26 07:37

A variable is just a location on the stack. Try and keep your variables with as small a scope as possible and try to make them final. However scope and final are just source code things... from a code generation/VM point of view they don't really matter at all.

In your specific example, using "int" no garbage is created. However if it were objects being created then for both cases the amount of garbage and when the garbage would be eligible for cleanup would be identical.

Take the following code:

public class X
{
    public static void main(final String[] argv)
    {
        foo();
        bar();
    }

    private static void foo()
    {
        for(int i=0;i<5;i++)
        {
            final int myFinalVariable = i;
        }
    }

    private static void bar()
    {
        for(int i=0;i<5;i++)
        {
            int myFinalVariable = i;
        }
    }
}

The compiler produces identical bytecode for each method:

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

public static void main(java.lang.String[]);
  Code:
   0:   invokestatic    #2; //Method foo:()V
   3:   invokestatic    #3; //Method bar:()V
   6:   return

private static void foo();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

private static void bar();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_0
   8:   istore_1
   9:   iinc    0, 1
   12:  goto    2
   15:  return

}

Adding another method that declares the variable outside the loop give you slightly different bytecode due to the order that the variables are declared). Note that this version the variable cannot be made final. This last version is not the best way (the final variable inside the loop is the best if you can do it):

private static void car()
{
    int myFinalVariable;

    for(int i=0;i<5;i++)
    {
        myFinalVariable = i;
    }
}

private static void car();
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   iconst_5
   4:   if_icmpge       15
   7:   iload_1
   8:   istore_0
   9:   iinc    1, 1
   12:  goto    2
   15:  return

}
查看更多
▲ chillily
5楼-- · 2020-01-26 07:43

Variable declared inside the loop have the scope only till the single execution of the loop.

Declaring the variable as final inside the loop makes the no difference for the variable in side the loop, but if we declare the variable outside the loop with final modifier then the value assigned to primitive type or Object assigned to the reference variable cannot be changed .

In the below example there is no issue with the first two loops both the loops give same output, but the third loop gives a compile time Error.

public class test {

public static void main(String[] args) {
    for (int i = 0; i < 5; i++) {
        final int j= i;
        System.out.println(j);
    }
    for (int i = 0; i < 5; i++) {
        int j= i;
        System.out.println(j);
    }

    final int j;
    for (int i = 0; i < 5; i++) {
        j= i;
        System.out.println(j);
    }
}

}

Please do correct me if i am wrong.

查看更多
一纸荒年 Trace。
6楼-- · 2020-01-26 07:46

You are right, for each iteration in the loop, you are creating a new variable. The variables do share the same name, but that's fine because they are not in the same scope. Next example would not work:

final int myFinalVariable = 0;
for(int i=0;i<5;i++){
  myFinalVariable = i;
}
查看更多
登录 后发表回答