Variables in Java β€” local, instance, static, final, var

A Java variable is a typed name bound to a memory slot. There are four kinds of variable depending on where it's declared, and several modifiers (final, static, volatile) that change its behaviour. The kind decides scope, lifetime and default value.

The four kinds of variable

KindDeclared inLifetimeDefault value
LocalMethod body or blockWhile the block runsNone β€” must be assigned before use
ParameterMethod or constructor signatureWhile the method runsCaller provides
Instance (field)Class body, no staticWhile the object livesType default (0, null, false)
Static (class field)Class body, with staticWhile the class is loadedType default

Scope β€” where the name is visible

public class Counter {
    private int total;          // instance β€” visible to all methods of Counter
    private static int count;   // static   β€” visible without an instance

    public void add(int n) {    // n is a parameter β€” visible in this method only
        int doubled = n * 2;    // local β€” visible until '}'
        total += doubled;
        count++;
    }
}

final β€” assign exactly once

final int LIMIT = 100;
LIMIT = 200; // ❌ "cannot assign a value to final variable LIMIT"

final List<String> names = new ArrayList<>();
names.add("Alice");           // βœ… the reference is final, the list is not

final on a reference variable means the variable can't be reassigned β€” it doesn't make the object immutable. For true immutability use records or unmodifiable collections.

var β€” local-variable type inference (Java 10+)

var users    = new ArrayList<User>();    // ArrayList<User>
var headers  = Map.of("X-Trace", "abc"); // Map<String,String>
var session  = repo.findById(id);         // whatever findById returns

// var is for locals only β€” won't compile here:
private var name;                         // ❌ instance fields can't use var
public var doStuff() { ... }              // ❌ method returns can't use var

Use var when the type is obvious from the right-hand side. Don't use it when the result type is unclear (e.g. var x = service.process(); hides whether you got a List or an Optional).

Naming conventions

  • Locals, parameters, instance fields: camelCase β€” userName, retryCount
  • Constants (static final): UPPER_SNAKE β€” MAX_RETRY, DEFAULT_TIMEOUT_MS
  • Boolean fields/methods: prefix with is, has, can β€” isActive, hasChildren

All sub-topics

Common mistakes

  • Reading an uninitialised local β€” Java rejects this at compile time. Initialise on declaration.
  • Mutable static state β€” global mutable state is a thread-safety nightmare. Prefer dependency injection.
  • Treating final as immutable β€” see the list example above.
  • Shadowing β€” a local with the same name as a field hides the field. Use this.field = ... to disambiguate (common in setters).

Try it & related tools

The Java Online Compiler shows the "might not be initialised" error in real time. For modern bean patterns without manual getters/setters, see the JSON to POJO tool (records, Lombok, classic).