creating final variables inside a loop

JavaFinal

Java Problem Overview


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 Solutions


Solution 1 - Java

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.

Solution 2 - Java

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;
}

Solution 3 - Java

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

}

Solution 4 - Java

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.

}

Solution 5 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJens JanssonView Question on Stackoverflow
Solution 1 - JavaGreg HewgillView Answer on Stackoverflow
Solution 2 - JavatehvanView Answer on Stackoverflow
Solution 3 - JavaTofuBeerView Answer on Stackoverflow
Solution 4 - JavaBasil BourqueView Answer on Stackoverflow
Solution 5 - JavaSetu PoddarView Answer on Stackoverflow