Methods & Scope
Variable Scope and Lifetime
You declare int i inside a for loop. Outside the loop, i doesn't exist.
Scope determines where a variable is visible. Understanding scope prevents bugs
and helps you write cleaner, more predictable code.
Block scope
Variables exist only within their enclosing braces.
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
public class BlockScope {
public static void main(String[] args) {
System.out.println("=== Block Scope ===\n");
int outer = ;
System.out.println("outer = " + outer);
{
// Inner block - can see outer
int inner = ;
System.out.println(" In block: outer = " + outer);
System.out.println(" In block: inner = " + inner);
// Nested block
{
int deepest = 30;
System.out.println(" Deepest: outer = " + outer);
System.out.println(" Deepest: inner = " + inner);
System.out.println(" Deepest: deepest = " + deepest);
}
// deepest is gone here
}
// inner is no longer accessible here!
System.out.println("After block: outer = " + outer);
// System.out.println(inner); // Error: cannot find symbol
System.out.println("\n=== Scope Rule ===");
System.out.println("Variables exist only in their { } block");
System.out.println("Inner blocks can see outer variables");
System.out.println("Outer blocks cannot see inner variables");
}
}
Variables declared inside {} are not visible outside those braces.
Variable shadowing
Inner variables can hide outer variables with the same name.
public class Shadowing {
static int x = 100; // Class-level x
public static void main(String[] args) {
System.out.println("=== Variable Shadowing ===\n");
System.out.println("Class-level x = " + x); // 100
int x = 50; // Local x shadows class x
System.out.println("Local x = " + x); // 50
System.out.println("Class x via class name = " + Shadowing.x);
{
int y = x + 10; // Uses local x (50)
System.out.println("Inner block uses local x: y = " + y);
// Cannot re-declare x in inner scope in Java!
// int x = 25; // Error: x already defined
}
// Method parameter shadowing
System.out.println("\n=== Method Parameter Shadowing ===");
processValue(999);
System.out.println("After method: x = " + x); // Still 50
System.out.println("\n=== Shadowing Summary ===");
System.out.println("Inner variables can hide outer ones");
System.out.println("Use class name to access shadowed static variables");
}
static void processValue(int x) { // Parameter shadows local
System.out.println("In method, parameter x = " + x); // 999
System.out.println("Class x = " + Shadowing.x); // 100
}
}
A local variable with the same name as a field "shadows" the field.
Loop variable scope
Loop variables are scoped to the loop block.
public class LoopScope {
public static void main(String[] args) {
System.out.println("=== Loop Variable Scope ===\n");
// For loop variable
System.out.println("For loop:");
for (int i = 0; i < 3; i++) {
System.out.println(" i = " + i);
}
// System.out.println(i); // Error: i not accessible
// Variable declared outside loop
System.out.println("\nVariable outside loop:");
int sum = 0;
for (int j = 1; j <= 5; j++) {
sum += j;
System.out.println(" j=" + j + ", sum=" + sum);
}
System.out.println("Final sum = " + sum); // sum still accessible
// Each iteration creates new local
System.out.println("\nNew variable each iteration:");
for (int k = 0; k < 3; k++) {
int temp = k * 10; // Created fresh each iteration
System.out.println(" k=" + k + ", temp=" + temp);
} // temp dies here, k dies here
// While loop scope
System.out.println("\nWhile loop:");
int count = 0; // Must declare outside
while (count < 3) {
int local = count * 2; // New each iteration
System.out.println(" count=" + count + ", local=" + local);
count++;
} // local dies, count survives
System.out.println("Final count = " + count);
}
}
The i in for (int i ...) only exists inside the loop body.
Method parameter scope
Parameters are local to the method.
public class MethodScope {
public static void main(String[] args) {
System.out.println("=== Method Scope ===\n");
int result = calculate(10, 5);
System.out.println("Result: " + result);
// Cannot access a, b, sum from here!
// System.out.println(a); // Error!
System.out.println("\n=== Multiple Calls ===");
System.out.println("calculate(20, 3) = " + calculate(20, 3));
System.out.println("calculate(7, 8) = " + calculate(7, 8));
// Each call has independent variables
System.out.println("\n=== Lifetime Demo ===");
trackLifetime();
trackLifetime(); // Same variable names, fresh values
}
static int calculate(int a, int b) {
// a and b are parameters - local to this method
System.out.println(" In calculate: a=" + a + ", b=" + b);
int sum = a + b;
int product = a * b;
System.out.println(" sum=" + sum + ", product=" + product);
return sum; // After return, a, b, sum, product all die
}
static int callCount = 0; // Class variable - persists
static void trackLifetime() {
callCount++; // Persists across calls
int localCounter = 1; // Dies after method ends
System.out.println("Call #" + callCount +
", localCounter=" + localCounter);
}
}
Parameters act like local variables, existing only during method execution.
Instance vs local variables
Distinguish between object fields and method-local variables.
public class InstanceVsLocal {
public static void main(String[] args) {
System.out.println("=== Instance vs Local Variables ===\n");
Counter c1 = new Counter("Counter-A");
Counter c2 = new Counter("Counter-B");
c1.increment();
c1.increment();
c1.increment();
c2.increment();
System.out.println("\n=== Final State ===");
c1.showCount();
c2.showCount();
System.out.println("\n=== Key Difference ===");
System.out.println("Instance vars: belong to object, persist");
System.out.println("Local vars: belong to method call, temporary");
}
}
class Counter {
// Instance variable - each Counter has its own
String name;
int count = 0;
Counter(String name) {
this.name = name;
}
void increment() {
int oldCount = count;
count++;
System.out.println(name + ": " + oldCount + " → " + count);
}
void showCount() {
System.out.println(name + " final count: " + count);
}
}
Instance variables live with the object. Local variables die when the method returns.
Exercise: ClosureLambda.java
Explore effectively final and lambda variable capture