Java Variables

BEGINNER ~8 min read Tutorial

A variable is a named location in memory that holds a value. Java variables come in three flavours: local variables inside methods, instance fields on objects, and class fields shared by all instances of a class. This tutorial focuses on local variables and instance fields; static fields get their full treatment in the classes tutorial.

Java is statically typed, which means every variable has a type known at compile time. The compiler uses that type to prevent you from assigning a String to an int, or calling a method that does not exist. This early error checking is the single biggest reason Java programs are stable in production: many bugs are caught by the compiler before they ever run.

1. Declaring and Initialising

To declare a variable, write the type followed by the name:

java
int age;
double price;
boolean isReady;
String name;

To initialise it, use the assignment operator =:

java
age = class="tok-num">30;
price = class="tok-num">19.99;
isReady = true;
name = "Alice";

You can combine declaration and initialisation on one line, which is the common form:

java
int age = class="tok-num">30;
double price = class="tok-num">19.99;
boolean isReady = true;
String name = "Alice";

class=class="tok-str">"tok-cmt">// type inference with var (Java class="tok-num">10+)
var city = "Toronto";   class=class="tok-str">"tok-cmt">// String
var count = class="tok-num">42;         class=class="tok-str">"tok-cmt">// int
var pi   = class="tok-num">3.14159;     class=class="tok-str">"tok-cmt">// double

Java 10 introduced var for local variables, which lets the compiler infer the type from the right-hand side. Use it when the type is obvious from the initialiser — var name = "Alice"; — and avoid it when the type is not obvious, e.g. var result = service.compute(); benefits from an explicit type for the reader.

2. Variable Types

Every variable has either a primitive type (one of the eight built-in) or a reference type (a class, interface, array or record). The difference matters when you assign or pass them:

  • Primitive variables hold the value directly. Assigning b = a copies the value.
  • Reference variables hold a reference (an address) to an object. Assigning b = a copies the reference, so both variables now point to the same object.
java
class=class="tok-str">"tok-cmt">// primitive: copy the value
int a = class="tok-num">10;
int b = a;       class=class="tok-str">"tok-cmt">// b now has its own copy of class="tok-num">10
b = class="tok-num">20;          class=class="tok-str">"tok-cmt">// a is still class="tok-num">10

class=class="tok-str">"tok-cmt">// reference: copy the reference
int[] x = {class="tok-num">1, class="tok-num">2, class="tok-num">3};
int[] y = x;     class=class="tok-str">"tok-cmt">// y now points to the same array as x
y[class="tok-num">0] = class="tok-num">99;       class=class="tok-str">"tok-cmt">// x[class="tok-num">0] is also class="tok-num">99 now

This distinction is the source of almost every “why did my object change?” question in early Java. Draw it on paper until it is intuitive.

3. Scope and Lifetime

A variable's scope is the region of code where the name is visible. Java scopes are lexical: a variable declared inside a block is visible only inside that block (and any nested block).

java
public class Scope {
    public static void main(String[] args) {
        int outer = class="tok-num">1;          class=class="tok-str">"tok-cmt">// visible until end of main
        if (outer == class="tok-num">1) {
            int inner = class="tok-num">2;      class=class="tok-str">"tok-cmt">// visible only inside this block
            System.out.println(outer + inner);   class=class="tok-str">"tok-cmt">// OK
        }
        class=class="tok-str">"tok-cmt">// System.out.println(inner);   // compile error: inner not visible
    }
}

Once the closing brace of the declaring block is reached, the variable is no longer accessible. The garbage collector may later reclaim the object it referred to, if nothing else references it.

4. Naming Conventions and Rules

Java variable names must:

  • Start with a letter, underscore, or dollar sign.
  • Contain only letters, digits, underscores or dollar signs thereafter.
  • Not be a Java keyword (class, int, return, …).

By convention, variable names use lowerCamelCase: firstName, orderId, maxRetries. Constants — final variables that never change — use UPPER_SNAKE_CASE: MAX_RETRIES, DEFAULT_PAGE_SIZE.

5. The final Keyword

Adding final to a declaration means the variable can be assigned exactly once. After that, any further assignment is a compile-time error:

java
final int maxUsers = class="tok-num">100;
maxUsers = class="tok-num">200;   class=class="tok-str">"tok-cmt">// compile error: cannot assign twice

final StringBuilder sb = new StringBuilder("hi");
sb.append("!");          class=class="tok-str">"tok-cmt">// OK - we are mutating the object, not the variable
class=class="tok-str">"tok-cmt">// sb = new StringBuilder();  // compile error: would reassign the reference

Use final liberally for local variables. It documents intent — “this value does not change” — and the compiler will catch accidental reassignments. Many teams adopt the rule “final by default” for locals and parameters, removing final only when reassignment is genuinely needed.

6. Instance Fields

Variables declared inside a class but outside any method are fields. Without static, they are instance fields: one copy per object. Every time you create an object with new, the JVM allocates fresh storage for each instance field.

java
public class BankAccount {
    class=class="tok-str">"tok-cmt">// instance fields - one set per object
    private String owner;
    private double balance;

    public BankAccount(String owner, double opening) {
        this.owner = owner;
        this.balance = opening;
    }
}

class=class="tok-str">"tok-cmt">// usage:
BankAccount a = new BankAccount("Alice", class="tok-num">100.0);
BankAccount b = new BankAccount("Bob",   class="tok-num">250.0);
class=class="tok-str">"tok-cmt">// a and b each have their own owner and balance

Instance fields hold the state of an object. They are usually marked private so code outside the class cannot modify them directly — this is encapsulation, covered in its own tutorial.

Exercises

  1. Declare an int, a double, a boolean, and a String. Print them all with System.out.println.
  2. Reproduce the reference-vs-primitive diagram above with two StringBuilder objects and print their values after each assignment.
  3. Write a method with a local variable declared inside an if block. Try to use it outside the block and read the compiler error.
  4. Mark five local variables final in a small program. Try to reassign one of them and confirm the compiler rejects it.