🧩 Methods · Beginner

Local variables & scope in Java

Locals live on the stack frame and die when the method returns.

🧩 The mysteryA counter method does count++ every single time it's called, and always returns 1. Is it broken, or just forgetful?

A method's private notes

Variables declared inside a method, including its parameters, are local. They exist only while that call runs and vanish when it returns. No other method can see them.

static int square(int n) { // n is local
    int result = n * n;    // so is result
    return result;
} // n and result are gone now
🔮 Predict it

Your turn

visit() is called three times. What prints?

static int visit() {
    int seen = 0;
    seen += 5;
    return seen;
}
void main() {
    visit();
    visit();
    System.out.println(visit());
}
  1. 15
  2. 5
  3. 0
Show the answer

5. Each call creates a new seen starting at 0, adds 5 and returns it. Nothing carries over between calls.

Where locals live

Locals live in the call's stack frame. Every call, even of the same method, gets brand-new copies; returning destroys the frame and its locals. (Objects a local *refers to* live on the heap.) To remember something between calls, use a field.

static int count = 0; // field: survives
static int next() {
    count++;
    return count; // 1, 2, 3, ...
}
⚠️ The trap

No default values

Locals get no default value. Reading one before it's definitely assigned is a compile error: variable x might not have been initialized. The compiler doesn't evaluate y > 0, so it sees a path where x was never set.

int x;
int y = 3;
if (y > 0) {
    x = 1;
}
System.out.println(x); // error
🔮 Predict it

Your turn

vip is true, so total gets 100... right?

int total;
boolean vip = true;
if (vip) {
    total = 100;
}
System.out.println(total);
  1. 100
  2. 0
  3. Compile error
Show the answer

Compile error. vip is an ordinary variable, so the compiler doesn't assume the if runs. It sees a path where total is unassigned. Fix: int total = 0;.

Sharing a value between methods

✗ Invisible
static void setUp() {
    int limit = 10;
}
static void run() {
    System.out.println(limit);
}

limit is local to setUp; run can't see it: cannot find symbol.

✓ Passed along
static void run(int limit) {
    System.out.println(limit);
}
// caller: run(10);

Pass it as a parameter (or, if it must persist, make it a field).

💼 In the real world

In real projects

Because each call has its own frame, and each thread its own stack, local variables are naturally thread-safe. That's why web servers can run the same method for thousands of requests at once: methods that keep their state in locals don't step on each other.

Key takeaways

  1. Locals and parameters disappear when the method returns
  2. Each call (even of the same method) gets its own fresh copies
  3. Locals have no default value; reading an unassigned one won't compile
  4. Another method can't see your locals
🤯 Did you know?

Inside the JVM, each frame stores locals in numbered slots, and a long or double takes up two slots while an int takes one.

Practice questions

What does this print?

static int next() {
    int count = 0;
    count++;
    return count;
}
void main() {
    next();
    next();
    System.out.println(next());
}
  1. 3
  2. 1
  3. 0
  4. 2
Check your answer

1. Each call creates a new count starting at 0, so every call returns 1.

What does this print?

int x;
int y = 3;
if (y > 0) {
    x = 1;
}
System.out.println(x);
  1. 1
  2. 0
  3. Compile error
Check your answer

Compile error. The compiler doesn't evaluate y > 0, so it sees a path where x is never assigned: variable x might not have been initialized. Locals have no default value.

Next: zoom out and watch the whole call stack grow and shrink as methods call methods.