Command Palette

Search for a command to run...

PHASE 1Beginner ~30 min· topic 1 of 14

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.

Main.javawhole filejava
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).

= means 'store', and the right side goes firstdiagram
Rendering diagram…

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.

Where the value lives: a slot in the stack framediagram
Rendering diagram…

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.

Main.javawhole filejava
int bonus;
boolean won = true;
if (won) {
    bonus = 100;
} else {
    bonus = 0;
}
System.out.println(bonus);   // fine: every branch assigned bonus

05Naming 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.

Swapping two values: why you need a third boxdiagram
Rendering diagram…

Try it yourself

  1. 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 coins already held 75 at that point.

  2. 2

    Break the swap

    In the swap example, delete the temp lines and try to swap a and b using only a = b; b = a;. Run it and explain the output in one sentence.

  3. 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 when temperature is 30 or less, advice is never assigned.

    terminal
    $ javac Main.java
    ── expected output ──
    Main.java:10: error: variable advice might not have been initialized
    System.out.println("It is " + temperature + " degrees: " + advice);
    ^
    1 error

Code & diagrams

Declare, assign, reassign New tab
Sign in to run this example in your browser.

Expected output

Start:  Asha has 3 lives and 50 coins
Later:  Asha has 2 lives and 75 coins
Switch: Ravi is playing now
Swap two variables with a temporary New tab
Sign in to run this example in your browser.

Expected output

before: a=7 b=42
broken: x=42 y=42
after:  a=42 b=7
Definite assignment follows every branch New tab
Sign in to run this example in your browser.

Expected output

It is 31 degrees: drink water
Legal and illegal names (fragment)java
int 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 operator

Break 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.

Main.javawhole filejava
public class Main {
    public static void main(String[] args) {
        int score;
        System.out.println(score);
    }
}
terminal
$ javac Main.java
── what you'll see ──
Main.java:4: error: variable score might not have been initialized
System.out.println(score);
^
1 error

Break #2

Declare the same name twice

Write int age = 10; and on the next line int age = 11;.

terminal
$ javac Main.java
── what you'll see ──
Main.java:4: error: variable age is already defined in method main(String[])
int age = 11;
^
1 error

Break #3

Misspell a name

Declare int total = 5; and print totl.

terminal
$ javac Main.java
── what you'll see ──
Main.java:4: error: cannot find symbol
System.out.println(totl);
^
symbol: variable totl
location: class Main
1 error

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. javac turns each local into a numbered slot in the frame's local variable array; names survive only in the optional LocalVariableTable debug attribute (javac -g), which is how debuggers show them. javap -c Main shows instructions like iconst_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.

  • ▸

    long and double locals 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. 1

    A declaration like int score; tells the compiler two facts: there is a variable called score, and it can only ever hold an int (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. 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. 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. 4

    Names follow strict rules: they may contain letters, digits, _ and $, must not start with a digit, are case-sensitive (total and Total are different variables), and can't be a keyword like int or class. By convention Java uses camelCase for variables: studentCount, maxSpeed, isReady.

  5. 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 int the value itself sits in that slot. For objects like String the slot holds a reference (an arrow) to the object on the heap. Topic 3.11 draws this picture in full.

  6. 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

01

What is the difference between declaring, initializing and assigning a variable? Give one line of Java for each.

02

Why does Java refuse to compile a read of an uninitialized local variable when C happily compiles it?

03

Where does the value of int n = 5; live while main runs, and what happens to it when main returns?

04

Why does a = b; b = a; not swap two variables?

Practice

01

Declare variables for a rectangle's width (8) and height (5). Print its area and perimeter on separate labelled lines.

02

Start with int balance = 100;. Deposit 40, withdraw 25, then double it, printing the balance after each step.

03

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 advice example).

  • ↔

    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.