Topic 1.1
Variables: Named Boxes for Values
In one line
A variable is a named place in memory that holds one value of a fixed type. You declare it once with a type and a name, give it a value before you read it, and can change that value later as long as the new value fits the type.
Think of it like this
Labelled jars in a kitchen. One jar says SUGAR, another says RICE. Each jar holds one kind of thing, the label never changes, but you can empty a jar and refill it. You can't pour rice into the jar marked SUGAR. A Java variable is a labelled jar: the name is the label, the type is the kind of thing it may hold, and the value is what's inside right now.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Variable
- A named place in memory that holds one value. You can read it and, unless it's
final, change it. - Type
- The kind of value a variable may hold, such as a whole number (
int), a decimal (double) or text (String). It also fixes how much memory the value takes. - Declaration
- The line that creates a variable by stating its type and name, like
int age;. - Assignment
- Storing a value into a variable with
=. The right side is worked out first, then stored on the left. - Initialization
- The very first assignment of a variable.
int age = 12;declares and initializes in one line. - Local variable
- A variable declared inside a method. It exists only while that method is running.
- Statically typed
- Every variable's type is known when the code is compiled, so type mistakes are caught before the program runs.
- Identifier
- Any name you invent in code: a variable, method or class name.
- Stack frame
- A small private area of memory a method gets while it runs. Its local variables live there and vanish when the method returns.
Step by step
01Declare, then assign
A declaration states the type first, then the name, then a semicolon. After that line, the variable exists but has no value yet. Assigning gives it one.
Most of the time you do both at once: int lives = 3;. This is called initializing the variable. It's the habit to build: declare a variable at the moment you have a value for it.
int lives; // declaration: a box named lives that holds an int
lives = 3; // assignment: put 3 in the box
int coins = 50; // declaration + initialization in one line
String player = "Asha";02= means 'store', and the right side goes first
Java always evaluates the whole right-hand side to one value, then stores it in the variable on the left. So coins = coins + 25; reads the current coins (50), computes 75, then overwrites the box with 75. The old value is gone.
That is why x = x + 1 is not a contradiction. In maths it would be, but here = is an action, not a statement of fact. Java's comparison 'is equal to' is a different operator, == (Topic 1.8).
03Where the value lives: a slot in the stack frame
When main starts, the JVM creates a stack frame for it with one slot per local variable. The compiler already decided how many slots are needed and which slot belongs to which variable, so at run time a variable is just a numbered slot. The bytecode instruction istore_1 means 'store an int into slot 1'.
For a primitive like int, the slot holds the number itself. For an object like String, the slot holds a reference (think of it as an arrow or an address) and the actual text lives in a shared area called the heap.
When main returns, the frame is thrown away, and with it every local variable. That's why local variables can't outlive their method.
04The compiler refuses to read an empty box
Local variables get no default value. If any path through the code could read a variable before it was assigned, javac stops with *variable ... might not have been initialized*.
The check is smart: it follows if/else branches. If every branch assigns the variable, reading it afterwards is fine. If even one branch forgets, compilation fails. This definite assignment analysis is defined in chapter 16 of the Java Language Specification.
Fields (variables that belong to an object, Phase 4) are different: they do get defaults like 0, false and null. Topic 1.2 shows them.
int bonus;
boolean won = true;
if (won) {
bonus = 100;
} else {
bonus = 0;
}
System.out.println(bonus); // fine: every branch assigned bonus05Naming rules and naming habits
The rules (the compiler enforces them): letters, digits, _ and $ only; no leading digit; no keywords such as int, class, new, for; case matters.
The habits (other programmers expect them): camelCase for variables (totalPrice), names that say what the value means rather than its type (ageInYears, not number1), is/has prefixes for booleans (isOpen), and UPPER_SNAKE_CASE only for constants (Topic 1.14). Avoid $ (generated code uses it) and single letters except for short loop counters.
Legal but bad: int a1, A1, a_1;. Illegal: int 2fast;, int class;, int my-age; (the dash is a minus sign).
06One name per scope, and changing the value, not the type
A variable's type is fixed for life. int count = 5; can later hold 6 or -40, but never "five" or 5.5; the compiler rejects both. If you need a different kind of value, you need a different variable.
Inside one scope, a name can be declared only once. Writing int age = 11; a second time is an error, even with the same type: you meant age = 11; (an assignment, no type in front).
07Swapping two values: why you need a third box
A classic beginner exercise is swapping the values in a and b. Writing a = b; b = a; fails: the first line overwrites a, so its old value is lost before you could copy it.
The fix is a temporary variable: save a, copy b into a, then copy the saved value into b. This tiny pattern appears everywhere, from sorting algorithms (see the DSA course at /dsa) to reversing arrays.
Try it yourself
- 1
Predict, then run
Open the first example. Before running it, add the line
coins = coins * 2;after the second print and write down what the next print will show. Then add a print and run it to check.You should see 150 coins, because
coinsalready held 75 at that point. - 2
Break the swap
In the swap example, delete the
templines and try to swapaandbusing onlya = b; b = a;. Run it and explain the output in one sentence. - 3
Make the compiler complain
In the definite-assignment example, delete the whole
else { ... }block and run. Read the error: the compiler has spotted that whentemperatureis 30 or less,adviceis never assigned.terminal$ javac Main.java── expected output ──Main.java:10: error: variable advice might not have been initializedSystem.out.println("It is " + temperature + " degrees: " + advice);^1 error
Code & diagrams
Expected output
Start: Asha has 3 lives and 50 coins
Later: Asha has 2 lives and 75 coins
Switch: Ravi is playing nowExpected output
before: a=7 b=42
broken: x=42 y=42
after: a=42 b=7Expected output
It is 31 degrees: drink waterint studentCount = 30; // good: camelCase, says what it means
int _hidden = 1; // legal, unusual
int $price = 9; // legal, avoid: $ is for generated code
int Total = 5; // legal, but Total and total are different
// int 2fast = 1; // error: a name can't start with a digit
// int class = 1; // error: class is a keyword
// int my-age = 1; // error: '-' is the minus operatorBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Read a variable before giving it a value
Declare int score; and print it straight away.
public class Main {
public static void main(String[] args) {
int score;
System.out.println(score);
}
}Break #2
Declare the same name twice
Write int age = 10; and on the next line int age = 11;.
Break #3
Misspell a name
Declare int total = 5; and print totl.
Myth vs fact
Myth
x = x + 1 is a contradiction, so it must be an error.
Fact
= means 'store'. Java computes x + 1 from the old value and stores the result back in x.
Myth
A new variable starts at 0 automatically.
Fact
Only fields and array elements get defaults. Local variables have none, and the compiler refuses to let you read one before you assign it.
Myth
Variable names are just labels, so case doesn't matter.
Fact
Java is case-sensitive. count, Count and COUNT are three different variables.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Local variable names are not needed at run time.
javacturns each local into a numbered slot in the frame's local variable array; names survive only in the optionalLocalVariableTabledebug attribute (javac -g), which is how debuggers show them.javap -c Mainshows instructions likeiconst_3/istore_1. - ▸
The JVM verifier repeats the definite-assignment check on bytecode: a class file that reads an unassigned slot is rejected at load time with a
VerifyError, so even hand-crafted bytecode can't read garbage memory. - ▸
longanddoublelocals take two slots each in the frame. The maximum number of slots and the maximum operand-stack depth are computed by the compiler and stored per method (max_locals,max_stack). - ▸
Declaring variables in the narrowest scope at first use is not only style: the JIT compiler's register allocator and the garbage collector's liveness analysis both benefit when a reference stops being live early.
Remember this
- 1
A declaration like
int score;tells the compiler two facts: there is a variable calledscore, and it can only ever hold anint(a whole number). Java is statically typed: the type is fixed when you write the code and checked by the compiler before the program ever runs. - 2
Assignment uses
=, which means *store the value on the right into the variable on the left*. It is not the maths 'equals'.score = score + 10;is perfectly sensible: read the old value, add 10, store the result back. - 3
A local variable (one declared inside a method) has no default value. The compiler tracks every path through your code and refuses to compile a read of a variable that might not have been given a value yet. This rule is called definite assignment, and it removes a whole class of bugs that C programs suffer from (reading leftover garbage memory).
- 4
Names follow strict rules: they may contain letters, digits,
_and$, must not start with a digit, are case-sensitive (totalandTotalare different variables), and can't be a keyword likeintorclass. By convention Java uses camelCase for variables:studentCount,maxSpeed,isReady. - 5
A local variable lives in the current method's stack frame, a small block of memory created when the method starts and thrown away when it returns. For primitive types like
intthe value itself sits in that slot. For objects likeStringthe slot holds a reference (an arrow) to the object on the heap. Topic 3.11 draws this picture in full. - 6
A variable is visible only inside the
{ }block where it is declared, from the line of its declaration onwards. This region is its scope. Two variables in the same scope can't share a name. Topic 3.6 covers scope and lifetime in depth.
Explain it without notes
What is the difference between declaring, initializing and assigning a variable? Give one line of Java for each.
Why does Java refuse to compile a read of an uninitialized local variable when C happily compiles it?
Where does the value of int n = 5; live while main runs, and what happens to it when main returns?
Why does a = b; b = a; not swap two variables?
Practice
Declare variables for a rectangle's width (8) and height (5). Print its area and perimeter on separate labelled lines.
Start with int balance = 100;. Deposit 40, withdraw 25, then double it, printing the balance after each step.
Rotate three variables: with a = 1, b = 2, c = 3, end with a = 2, b = 3, c = 1 using exactly one temporary variable.
Trade-offs
- ↔
Declaring a variable at first use keeps scope small and code readable, but declaring it earlier is sometimes needed so that several branches can assign it (as in the
adviceexample). - ↔
Short names (
i,n) keep tight loops readable; long descriptive names make business logic self-explaining. Match name length to how far away the reader is from the declaration.
Done when you can
I can declare, initialize and reassign a variable and explain what
=really does.I can explain definite assignment and fix 'might not have been initialized'.
I know the naming rules and the camelCase convention.
I can describe where a local variable lives in memory and when it disappears.
I can swap two variables correctly and explain why the naive version fails.