Re-declaring variables inside loops in Java

In Java, we cannot declare a variable in the same scope with the other variable which has the same name:

int someInteger = 3;

...

int someInteger = 13;

Syntax error, doesn't compile. However, if we put it inside a loop:

for (int i = 0; i < 10; i++) {
   int someInteger = 3;
}

Generates no error, works very well. We are basicly declaring the same variable. What is the reason? What is the logic that I don't know/understand behind this?


Think of this way, after each loop, the scope is "destroyed", and the variable is gone. In the next loop, a new scope is created, and the variable can be declared again in that scope.

You can also do this, for the similar reason

{
   int someInteger = 3;
}
{
   int someInteger = 13;
}

By the way, Java does not allow local variable shadowing, which might be inconvenient

int x = 3;
{
   int x = 13; // error!
}

Consumer<Integer> consumer = (x)->print(x);  // ERROR! 
// lambda parameter is treated like local variable

Runnable r = ()->{ int x; ... } // ERROR
// lambda body is treated like local block

Java has what is called 'block scoping' which means whatever block of code (defined by the enclosing curly braces) a variable is declared in, that (and only there) is where it exists. It also means that each variable can only be declared once in any given block.

When you say

for (int i = 0; i < 10; i++) {
  int someInteger = 3;
}

A new block is created on every iteration. It's similar to saying

{ 
  int someInteger = 3;
}
{ 
  int someInteger = 3;
}
...

In which case there is only 1 variable named someInteger in each block.

When you say

{ 
  int someInteger = 3;
  ...
  int someInteger = 3;
}

The compiler correctly complains that you are declaring more than one variable with the same name in the same block (or scope) of code.


Within the scope of a block, a new someInteger is created and it shadows the lexical scope of anyother someInteger. The Wikipedia entry on Variable shadowing says (in part)

variable shadowing occurs when a variable declared within a certain scope (decision block, method, or inner class) has the same name as a variable declared in an outer scope. At the level of identifiers (names, rather than variables), this is known as name masking.


Every variables have a scope. A scope is nested inside a bracket {}. when you go out of this scope, this context is gone, so you can defined other variables with same name. Otherwise, you cannot.

I will give you two examples:

// define new scope named "methodA"
public void methodA() {
   int a = 3; 
   // define new scope named "loop"
   for (int i = 0; i < 10; i++) {
      int a = 6; // ERROR
   }
}

In above case, you will meet error. because "loop" scope is inside "methodA" scope, so first definition of a still exist when you go to "loop" scope.

Second case:

// define new scope named "methodA"
public void methodA() {
   // define new scope inside methodA scope
   {
       int a = 3;
   } 
   // define new scope named "loop"
   for (int i = 0; i < 10; i++) {
      int a = 6; // NO ERROR
   }
}

above code will compiled successfully, because first definition of a in different scope of second definition of a, and those scopes don't nested.