Skip to content
Laviyx Learn

Try

Java course menu

Java Scope and static: Local Variables, Fields and Class Members

Understand variable scope in Java: block scope, local variables, why Java forbids shadowing locals, fields vs local variables, static fields and methods shared by the whole class, and instance members.

Beginner8 min readUpdated
On this page

Every variable has a scope: the part of the code where its name can be used. Java's scope rules are simple and strict, and they explain many "cannot find symbol" errors. This lesson also explains the static keyword you have been writing since your first program.

Block scope#

A variable declared inside a block { } exists only from its declaration to the end of that block:

Java
public class Main {
    public static void main(String[] args) {
        int total = 0;
        for (int i = 1; i <= 3; i++) {
            int square = i * i;      // exists only inside the loop body
            total += square;
        }
        System.out.println(total);
        // System.out.println(square);   // error: cannot find symbol
        // System.out.println(i);        // error: i belongs to the for loop
    }
}
Output
14

Declare variables in the smallest scope that needs them.

Local variables in methods#

Each method call has its own local variables, including its parameters. Two methods can use the same names without any conflict, and locals are discarded when the method returns:

Java
public class Main {
    static int doubleIt(int value) {
        int result = value * 2;
        return result;
    }

    public static void main(String[] args) {
        int result = doubleIt(21);   // a different 'result'
        System.out.println(result);
    }
}
Output
42

No shadowing of locals#

Unlike C++, Java does not allow a local variable to be redeclared in a nested block of the same method:

Java
public class Main {
    public static void main(String[] args) {
        int level = 1;
        if (level > 0) {
            int level = 99;   // error: variable level is already defined
        }
    }
}

This rule prevents a whole class of confusing bugs.

Fields: variables that belong to the class#

Variables declared inside a class but outside any method are fields. They are visible to every method in the class and live as long as their object (or class) does. Unlike local variables, fields get a default value (0, false, null) if you do not initialize them.

static: shared by the whole class#

A static field belongs to the class itself, so there is exactly one copy, shared by everything that uses the class. A static method also belongs to the class, and can be called without creating an object:

Java
public class Counter {
    static int requestCount = 0;   // one shared counter

    static void handleRequest() {
        requestCount++;
    }

    public static void main(String[] args) {
        handleRequest();
        handleRequest();
        handleRequest();
        System.out.println(requestCount);
    }
}
Output
3

Familiar examples from the standard library: Math.sqrt(...), Integer.parseInt(...) and Math.PI are all static, so you call them on the class name.

static vs instance members#

Members without static are instance members: each object has its own copy of instance fields, and instance methods work on a particular object. You will use them throughout the OOP section; here is a preview:

Java
public class Ticket {
    static int issued = 0;   // shared: counts all tickets
    int number;              // per object: each ticket has its own number

    Ticket() {
        issued++;
        number = issued;
    }

    public static void main(String[] args) {
        Ticket a = new Ticket();
        Ticket b = new Ticket();
        Ticket c = new Ticket();
        System.out.println(a.number + " " + c.number);
        System.out.println("Issued: " + Ticket.issued);
    }
}
Output
1 3
Issued: 3

Rules to remember:

  • A static method cannot use instance fields or call instance methods directly, because there is no particular object (no this). This is why calling a non-static helper from main fails.
  • An instance method can use both instance and static members.

Effectively final variables#

Lambdas and anonymous classes (covered later) may only use local variables that are effectively final: never changed after initialization. If you see "local variables referenced from a lambda expression must be final or effectively final", the variable is reassigned somewhere.

Avoid mutable static state#

Like global variables in other languages, mutable static fields can be changed from anywhere, which makes bugs hard to trace and causes problems with multiple threads. Static constants (static final) and static utility methods (such as Math.max) are fine.

Common mistakes#

Practice#

Practice exercise

Write a class Logger with a static counter and a static method log(String text) that prints messages numbered [1] ..., [2] ... and so on. Log three messages.

Show solution
Java
public class Logger {
    static int count = 0;

    static void log(String text) {
        count++;
        System.out.println("[" + count + "] " + text);
    }

    public static void main(String[] args) {
        log("Started");
        log("Loading");
        log("Done");
    }
}
Output
[1] Started
[2] Loading
[3] Done

Key takeaway#

Finished this lesson?