13

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?

4
  • 1
    We are basicly declaring the same variable. Are you? How can you access its previous value? Commented Jun 16, 2015 at 2:12
  • 2
    Garbage collection. Variables in the loops are no longer in scope as the program executes. Commented Jun 16, 2015 at 2:14
  • 1
    @MalikBrahimi: It's true that variables inside the loop are no longer in scope outside the loop, but the reason is not "garbage collection". Garbage collection refers to disposal of objects allocated with new. Commented Jun 16, 2015 at 2:16
  • 1
    Java variables are block-scoped. For the rest, Google "Java shadowing". Commented Jun 16, 2015 at 2:17

7 Answers 7

13

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
Sign up to request clarification or add additional context in comments.

Comments

4

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.

Comments

2

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.

Comments

2

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.

1 Comment

can be shadowed by local/anonymous class though... but not by lambda
0

You can re-use the same variable name within a class or method if it is in a different scope to the first use.

In your first example, the two variables have the same scope and hence the name clashes and the compiler reports an error. In your second example, they have a different scope - one is in the method, the other within the for loop - hence there is no clash and the code compiles.

Comments

-1

Different scopes;

int variables = 3;
....
int variables = 13;

Scope unanimously, certainly compile error; But

for (;;;) {
     int variables = 13;
}

Every cycle is equivalent to re-establish the variables variables variables before disappear with the change of scope; JVM stack frame is such a mechanism (local variables with the start of the assignment process, with the end of the process and eliminating);

Comments

-1

You can push your variable into an array.

Stack myarr = new Stack();
for (int i = 0; i < 10; i++) {
   int someInteger = 3;
myarr.push(someInteger);
}

or create a variable everyloop

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.