Java Local Variables
Table of Contents + β
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:
messageis born whenwelcomestarts and dies when it returns.- Call
welcomeagain and you get a brand new, emptymessage. - The parameter
nameis 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 becomes0. - 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 resultTo 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 nowInside the loop, i works fine. After the closing brace it is gone, so the last line fails to compile:
Compile error
error: cannot find symbolSystem.out.println("final " + i); ^ symbol: variable iThis 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 0first loop 1second loop 0second loop 1Both 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.99var 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 theAccountobject exists.amount(parameter) carries the value passed in by the caller.fee(local) exists only whiledepositruns.- After the method ends,
amountandfeeare gone, butbalancekeeps its new value.
Output
98Deposit 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 valueint sum() { int total; return total + 1;}
// β
Right: give it a value firstint 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 blockvoid greet(boolean ok) { if (ok) { String message = "Hi"; } System.out.println(message); // cannot find symbol}
// β
Right: declare it in the wider scopevoid 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 fieldclass User { String name; void setName(String name) { name = name; // assigns the parameter to itself, field stays null }}
// β
Right: this.name points at the fieldclass 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 typevar 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
iin the next loop is fine. - Use
varonly when the type is obvious from the value. When in doubt, write the type out so the code reads clearly. - Use
thiswhen 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
varkeyword (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
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
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
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
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.