Java Variable Scope
Understand where a Java variable is visible — local, instance, class (static), and block scope.
The scope of a variable is the region of the program where you're allowed to use its name. A name declared inside one method isn't visible from another; a name declared inside a for loop isn't visible after the loop. The compiler enforces these rules strictly — try to reach a name outside its scope and your code won't compile.
Java has three main kinds of variables, each with its own scope: local variables (including parameters), instance fields, and class fields. This chapter focuses on local scope since that's what shapes the methods you've been writing.
Local variables
A local variable is declared inside a method or a block, and is visible only from the point of declaration to the end of the enclosing block:
public static int demo() {
int x = 1; // x is in scope from here...
System.out.println(x);
return x;
} // ...to here
// System.out.println(x); // ERROR: x not visible outside demo()Local variables are not initialized by Java — you must assign a value before reading. The compiler tracks definite assignment and refuses to compile a read of a possibly-unassigned local.
Block scope
Curly braces define a block. Variables declared inside a block are visible only inside that block, including nested blocks but not outside:
public static void blocks() {
int outer = 10;
if (outer > 0) {
int inner = 20;
System.out.println(outer + inner); // both visible
}
// System.out.println(inner); // ERROR: inner is out of scope here
}This applies to if, for, while, do-while, switch, and to bare { ... } blocks you write for grouping. A for's loop variable is in scope only inside the loop:
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
// System.out.println(i); // ERROR: i is out of scopeIf you need the index after the loop, declare i outside:
int i = 0;
for (; i < 3; i++) {
System.out.println(i);
}
System.out.println("stopped at " + i);Method parameters
Parameters are local variables that happen to be initialized by the caller. Their scope is the entire method body, from the opening brace to the closing one:
public static int square(int n) { // n is in scope from here...
return n * n;
} // ...to hereEach call gets its own set of parameter slots, so recursive calls don't interfere with each other.
Shadowing
Java forbids declaring a local variable with the same name as one that's already in scope in the same block or an enclosing block of the same method:
public static void clash() {
int x = 1;
// int x = 2; // ERROR: variable x is already defined
if (true) {
// int x = 3; // ERROR: x is in scope from the outer block
}
}This is stricter than what many languages allow — Java assumes that re-using a name inside a method is a mistake. (Instance and class fields can be shadowed by local variables of the same name; we'll get to that in the OOP part of the book.)
Lifetime vs. scope
Scope is where you can use the name. Lifetime is how long the underlying storage exists. They usually line up — when a local goes out of scope, its slot is gone — but for objects the distinction matters:
public static String makeName() {
String s = new String("Ada"); // s in scope here
return s;
} // s out of scope, but the String object lives onThe variable s disappears, but the String object it referenced is still alive — the caller holds a reference, so the garbage collector won't reclaim it. Local variables limit names, not object lifetimes.
A glimpse of instance and class fields
Inside a class, alongside methods, you can declare fields — variables whose scope is the whole class. There are two flavors:
- Instance fields belong to each object created from the class. Each
Doghas its ownnameandage. - Class fields (declared
static) belong to the class itself; there's one shared copy.
public class Counter {
private static int totalCreated = 0; // class field — one shared
private int value = 0; // instance field — one per Counter
public Counter() {
totalCreated++;
}
public void inc() {
value++; // refers to this instance's field
}
}We won't go deeper here — the Classes and Objects part covers fields properly. The short version: fields are visible everywhere in the class; locals are visible only in the block they're declared in.
A worked example
What's next
Scope tells you where a name lives. The next question — once you've passed an argument into a method — is what the method actually has. The pass-by-value chapter clears up the most common confusion in Java: what's really going on when you pass an object reference.
Practice
Where is a variable declared inside an if block visible?