Blocks & variable scope in Java
Variables live only inside their { } block.
Rooms with walls
A pair of braces { } forms a block. A variable's scope is the region of code where its name can be used: from its declaration to the closing brace of its block. After that }, the variable is gone.
int total = 0;
if (total == 0) {
int bonus = 5;
total += bonus;
}
// bonus doesn't exist hereInside sees out, not the other way
Code inside a block can see variables from the outer blocks (total above). Code outside can't see in. Using bonus after its } fails with cannot find symbol. Think of a one-way mirror: the inner room looks out, the outer room can't look in.
int age = 20;
if (age >= 18) {
String label = "adult";
}
System.out.println(label); // errorSame name, twice?
Two separate blocks both declare x. What happens?
{
int x = 1;
System.out.println(x * 10);
}
{
int x = 2;
System.out.println(x * 10);
}Compile error10 2010 10
Show the answer
10 then 20. The first x dies at its closing brace, so the name is free again. Sibling blocks may each declare their own variable with the same name.
No twins in nested blocks
Here the outer count is still in scope inside the inner block. Java forbids a local variable from hiding (shadowing) another local that's still alive: variable count is already defined. (A local may shadow a class field, but never another local.)
int count = 1;
{
int count = 2; // compile error
}Your turn
What happens here?
int level = 1;
if (level > 0) {
int level = 2;
System.out.println(level);
}21Compile error
Show the answer
Compile error. The outer level is still in scope inside the if block, so declaring another level there is rejected. Just assign it instead: level = 2;.
Using a value after if/else
if (temp > 30) {
String msg = "hot";
} else {
String msg = "mild";
}
System.out.println(msg);Each msg dies at its own brace, so the println can't find either one.
String msg;
if (temp > 30) {
msg = "hot";
} else {
msg = "mild";
}
System.out.println(msg);Declare it before the if, assign it in each branch. The compiler can prove it's set on every path.
In real projects
Experienced developers declare each variable in the smallest block that needs it. Narrow scope means fewer places a value can be changed by accident and less to keep in your head while reading. "cannot find symbol" is one of the most common compile errors beginners meet, and it's almost always a scope question.
Key takeaways
- Scope = the region of code where a name can be used
- A variable declared in an if or loop block is gone after its }
- A local can't be redeclared with the same name inside a nested block
- Sibling blocks may each declare their own variable with the same name
💡 A block is like a room: things set down inside stay in that room, but you can still see the furniture in the hallway outside.
C and C++ allow an inner block to declare a variable with the same name as an outer one, silently hiding it. Java's designers banned that for local variables to prevent a whole family of confusing bugs.
Practice questions
What does this print?
{
int n = 3;
System.out.println(n);
}
{
int n = 7;
System.out.println(n);
}- Compile error
- 3 7
- 3 3
- 7 7
Check your answer
3 7. The first n's scope ends at its closing brace, so the name is free to be declared again in the next, separate block.
You want to print msg after the if/else. What's the best fix?
if (temp > 30) {
String msg = "hot";
} else {
String msg = "mild";
}
System.out.println(msg);- Make msg static inside each block
- Rename one of the two msg variables
- Declare String msg; before the if and assign it in each branch
- Add return msg; at the end of each block
Check your answer
Declare String msg; before the if and assign it in each branch. Declaring msg in the outer block gives it a scope that covers both branches and the println. The compiler can also prove it's assigned on every path.