Java Local Variables

In the last lesson you learned about Java fields and methods. Inside a method you keep needing little helper values like a running sum or a loop counter. Local variables are those short-lived values that live right where you use them and vanish when you are done.

πŸ“ What a local variable is

A local variable means β€œtied to one spot.”

  • You declare it inside a method, constructor, or block.
  • It is not a field on the object.
  • Nothing outside that code can see it.
  • When the method finishes, the variable is gone.

Here is a method that builds a greeting using a local variable, then returns it:

public class Main {
public static void main(String[] args) {
Greeter g = new Greeter();
System.out.println(g.welcome("Alex"));
}
}
class Greeter {
String welcome(String name) {
String message = "Hello, " + name + "!"; // local variable
return message;
}
}

Output

Hello, Alex!

How the locals behave here:

  • message is born when welcome starts and dies when it returns.
  • Call welcome again and you get a brand new, empty message.
  • The parameter name is local too. Parameters count as locals, appearing on call and vanishing on return.

🧠 Local variables have no default value

This rule trips up most beginners.

  • A field gets a default for free. int age; as a field becomes 0.
  • A local does not get that gift.
  • Read a local before assigning it and the code will not even compile.

This method declares a local but reads it before giving it a value, so Java refuses to build it:

int badTotal() {
int sum; // ❌ declared, but never given a value
return sum + 5; // ❌ trying to read sum here
}

The compiler stops you with a clear complaint:

Compile error

error: variable sum might not have been initialized
return sum + 5;
^

The fix: give the local a value before you read it.

int goodTotal() {
int sum = 0; // βœ… assigned before use
return sum + 5; // βœ… now it is safe to read
}

Java does this to protect you. A field that quietly defaults to 0 can hide a bug, so Java forces you to say what you mean. Always initialize a local variable before you read it.

A field, by contrast, compiles fine because it gets a default:

class Counter {
int value; // field: Java sets it to 0 for you
int show() {
return value; // βœ… fine, value already holds 0
}
}

Same type, but a field is safe to read while a bare local is not. That is the core contrast.

πŸ”² Scope: the braces decide

A variable’s scope is the region of code where it exists.

  • It is visible from the line you declare it down to the block’s closing brace.
  • Outside those braces, it does not exist.

This method declares a variable inside an if block and then tries to use it after the block ends:

void check(int score) {
if (score > 50) {
String result = "pass"; // lives only inside these braces
System.out.println(result);
}
System.out.println(result); // ❌ result does not exist here
}

The first println shares the braces with result, so it works. The second sits outside, so result is already gone. Java will not compile this:

Compile error

error: cannot find symbol
System.out.println(result);
^
symbol: variable result

To use the value after the block, declare the variable in the wider scope:

void check(int score) {
String result = "fail"; // declared in the method's scope
if (score > 50) {
result = "pass"; // βœ… just assigning, not redeclaring
}
System.out.println(result); // βœ… result is still in scope here
}

Now result is declared in the method body, so it is visible everywhere inside, including after the if. The inner block only changes its value. A local variable lives only inside the braces where it was declared.

πŸ” Loop variables are local too

A variable declared in a for loop header is local to that loop.

  • It exists while the loop runs.
  • It disappears when the loop ends.
  • Read it afterward and you get the same scope error.

This loop counts from 0 to 2, then tries to print the counter after the loop:

for (int i = 0; i < 3; i++) {
System.out.println("i = " + i); // βœ… i is in scope inside the loop
}
System.out.println("final " + i); // ❌ i is gone now

Inside the loop, i works fine. After the closing brace it is gone, so the last line fails to compile:

Compile error

error: cannot find symbol
System.out.println("final " + i);
^
symbol: variable i

This scoping helps you. Because i dies with the loop, you can reuse the name i in the next loop with no clash. Each loop gets its own clean i.

This program runs two separate loops, each with its own i, and they never interfere:

public class Main {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
System.out.println("first loop " + i);
}
for (int i = 0; i < 2; i++) {
System.out.println("second loop " + i);
}
}
}

Output

first loop 0
first loop 1
second loop 0
second loop 1

Both loops use i because the first i was gone before the second started. Need the counter after the loop? Declare it before the loop, like result earlier.

πŸ†• The var keyword

Since Java 10, var lets Java work out a local’s type from the value you assign. This is called type inference. You write less, but the variable still has a real, fixed type.

This method declares three locals with var, and Java infers each type from the value:

void demo() {
var name = "Alex"; // Java infers String
var count = 10; // Java infers int
var price = 9.99; // Java infers double
System.out.println(name + " " + count + " " + price);
}

Output

Alex 10 9.99

var is not an β€œany type” box. Once Java infers count as int, it stays int forever. Two things to remember:

  • It works for local variables only, not fields or parameters.
  • You must assign a value on the same line, or Java cannot infer the type. var x; does not compile.

Use var when the type is obvious

var reads best when the right side already tells you the type, like var list = new ArrayList<String>(). If the type is not obvious from the value, write the type out in full so your code stays easy to read.

🧩 Local vs instance vs parameter

Three things look like variables inside a class:

  • Local variable β€” declared inside a method body.
  • Instance variable (field) β€” declared in the class, outside any method; belongs to the object.
  • Parameter β€” the value passed into a method; acts like a local.

This class shows all three in one place:

public class Main {
public static void main(String[] args) {
Account a = new Account();
a.deposit(100);
System.out.println(a.balance);
}
}
class Account {
int balance; // instance variable: belongs to the object
void deposit(int amount) { // amount: parameter, acts like a local
int fee = 2; // local variable: lives only in deposit
balance = balance + amount - fee;
}
}

What each one does:

  • balance (instance) sticks around as long as the Account object exists.
  • amount (parameter) carries the value passed in by the caller.
  • fee (local) exists only while deposit runs.
  • After the method ends, amount and fee are gone, but balance keeps its new value.

Output

98

Deposit 100 minus fee 2 leaves 98. The instance variable remembered the result. The locals did their job and disappeared.

The big difference

Instance variables get default values and live with the object. Local variables (and parameters) get no defaults, must be assigned before use, and vanish when the method ends. When you need data to last beyond one method call, use a field. For short, throwaway work, use a local.

⚠️ Common Mistakes

Watch for these slip-ups.

Using a local before initializing it. Fields get a default, so people assume locals do too. They do not, and the code will not compile.

// ❌ Wrong: total is read before it has a value
int sum() {
int total;
return total + 1;
}
// βœ… Right: give it a value first
int sum() {
int total = 0;
return total + 1;
}

Using a variable outside its scope. Declaring a local inside a block and then reaching for it after the closing brace fails, because it no longer exists.

// ❌ Wrong: message dies with the if block
void greet(boolean ok) {
if (ok) {
String message = "Hi";
}
System.out.println(message); // cannot find symbol
}
// βœ… Right: declare it in the wider scope
void greet(boolean ok) {
String message = "";
if (ok) {
message = "Hi";
}
System.out.println(message);
}

Shadowing a field with a local of the same name. When a local or parameter has the same name as a field, the local wins inside the method, so the field never changes. Use this to point clearly at the field.

// ❌ Wrong: "name" here means the parameter, not the field
class User {
String name;
void setName(String name) {
name = name; // assigns the parameter to itself, field stays null
}
}
// βœ… Right: this.name points at the field
class User {
String name;
void setName(String name) {
this.name = name; // field gets the parameter's value
}
}

Trying to use var without a value. var needs a value on the same line so Java can work out the type. A bare declaration does not compile.

var count; // ❌ no value, Java cannot infer the type
var count = 0; // βœ… Java infers int from the value

βœ… Best Practices

  • Always assign a local before you read it. Java will stop you anyway, so set it up front and move on.
  • Declare locals in the smallest scope that works. If a value is only needed inside a loop, declare it inside the loop. Tight scope means fewer surprises.
  • Declare a local close to where you first use it. It keeps the value and its use right next to each other, which is easier to follow.
  • Reuse loop variable names freely. Each loop’s counter dies with the loop, so a fresh i in the next loop is fine.
  • Use var only when the type is obvious from the value. When in doubt, write the type out so the code reads clearly.
  • Use this when a parameter shadows a field. It removes any doubt about which one you mean.

🧩 What You’ve Learned

  • βœ… A local variable is declared inside a method or block and exists only while that code runs.
  • βœ… Its scope is the braces it sits in; outside those braces it does not exist.
  • βœ… Local variables have no default value; you must initialize one before reading it or the code will not compile.
  • βœ… Instance variables are different: they get defaults (0, false, null) and live with the object.
  • βœ… Loop variables are local to the loop, so you can safely reuse the same name in another loop.
  • βœ… The var keyword (Java 10+) lets Java infer a local’s type from its value, but only for locals with a value on the same line.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    Where does a local variable exist?

    Why: A local variable is created when its method or block starts and disappears when that code ends.

  2. 2

    What happens if you read a local variable before assigning it?

    Why: Local variables have no default value, so Java gives a 'variable might not have been initialized' compile error.

  3. 3

    What decides the scope of a local variable?

    Why: A local variable is visible from its declaration down to the closing brace of its block.

  4. 4

    What is true about the var keyword?

    Why: var infers the type from the value on the same line and can only be used for local variables.

πŸš€ What’s Next?

You know how short-lived local data works. Next, look at data that belongs to the object and lasts as long as the object does.

Java Instance Variables

Share & Connect