JavaBasicsbeginner
Updated:

Java Variables: Declaration, Types and Scope

6 min read

Learn how Java variables are declared and initialized, the difference between local, instance and static variables, and how scope decides what your code can see.

TL;DR – Quick Answer

A Java variable is a named container for a value, declared with a type: for example, int count = 10. Java has three kinds — local variables (inside methods), instance variables (one copy per object) and static variables (one copy per class). Where you declare a variable decides its scope, its lifetime and whether it gets a default value.

On This Page

Variables look like the most trivial topic in Java — until an interviewer asks why a local variable gave a compile error while an identical field silently worked, or why changing a static variable in one object "changed" it in another. Those questions are really about the three kinds of variables and their scope rules, and this page gives you the complete picture.

Declaring and initializing variables

A declaration names a variable and fixes its type. An initialization gives it its first value. You can do them separately or together:

public class Declarations {
    public static void main(String[] args) {
        int batchSize;              // declaration only
        batchSize = 25;             // initialization later

        double feePerMonth = 8500.0;      // declare + initialize
        String trainer = "Siva";          // reference type variable
        boolean isWeekendBatch = false;

        int rows = 3, cols = 4;     // legal, but one per line reads better

        System.out.println(trainer + " runs a batch of " + batchSize
                + " at " + feePerMonth + "/month, weekend: " + isWeekendBatch
                + ", grid " + rows + "x" + cols);
    }
}

Once declared, a variable's type is fixed forever — batchSize = "twenty" will not compile. That is the static typing you met in Java data types: the compiler guards every assignment.

Since Java 10 you can also let the compiler infer the type of a local variable with var:

var count = 10;                       // inferred as int
var names = new java.util.ArrayList<String>();  // inferred as ArrayList<String>

var is not dynamic typing — the type is still fixed at compile time, you just skipped writing it. It works only for local variables with an initializer, never for fields or parameters.

Naming rules and conventions

The compiler enforces a few rules: names start with a letter, $ or _, contain no spaces or hyphens, and cannot be keywords like class or int. Names are case-sensitive — fee and Fee are different variables.

The conventions matter more in practice, because every Java team follows them:

Kind Convention Example
Variables and methods camelCase totalMarks, studentName
Classes PascalCase StudentRecord
Constants (static final) UPPER_SNAKE_CASE MAX_ATTEMPTS

Pro tip: Name variables for what they contain, not how they are used in one line. monthlyFee survives refactoring; temp2 guarantees that in three weeks even you will not know what it holds. Interviewers reading your machine-round code absolutely judge naming.

The three kinds of variables

This is the heart of the topic. Java classifies every variable by where it is declared, and that placement decides its lifetime, its default value and who shares it.

public class Student {

    static String institute = "CodeBegun";   // static variable: one per CLASS
    String name;                              // instance variable: one per OBJECT
    int score;                                // instance variable

    void printReport() {
        int passMark = 40;                     // local variable: one per CALL
        String result = (score >= passMark) ? "PASS" : "FAIL";
        System.out.println(institute + " | " + name + ": " + score
                + " -> " + result);
    }

    public static void main(String[] args) {
        Student a = new Student();
        a.name = "Anil";
        a.score = 72;

        Student b = new Student();
        b.name = "Bhavya";
        b.score = 35;

        a.printReport();   // CodeBegun | Anil: 72 -> PASS
        b.printReport();   // CodeBegun | Bhavya: 35 -> FAIL

        Student.institute = "CodeBegun Hyderabad";  // changes for EVERYONE
        a.printReport();   // CodeBegun Hyderabad | Anil: 72 -> PASS
    }
}

Walk through what each variable did:

  • institute (static): one copy exists for the whole class. Changing it through Student.institute affected what a printed, because a never had its own copy — all objects read the same one.
  • name and score (instance): a and b each carry their own values. This per-object state is what makes objects useful, and controlling access to it is the entire point of encapsulation.
  • passMark and result (local): born when printReport() starts, gone when it returns. Each call gets fresh copies.
Property Local Instance Static
Declared inside a method/block in class, no static in class, with static
Copies one per method call one per object one per class
Default value none — must assign yes (0, false, null) yes (0, false, null)
Lives on stack frame heap (inside object) class metadata
Accessed via its own name object reference class name

Interview note: "Where are variables stored in memory?" is a frequent follow-up. Local variables (and references) live on the thread's stack; objects and their instance variables live on the heap; static variables live with the class. Precision here signals you understand the JVM, not just syntax.

Default values: the rule that trips everyone

Instance and static variables get automatic defaults — 0, 0.0, false, null. Local variables get nothing, and the compiler blocks any read before assignment:

public class Defaults {
    static int classCounter;      // defaults to 0
    int attempts;                 // defaults to 0

    public static void main(String[] args) {
        System.out.println(classCounter);      // 0 — fine

        int local;
        // System.out.println(local);          // compile error: not initialized
        local = 5;
        System.out.println(local);             // fine after assignment
    }
}

Common mistake: A common mistake beginners make is expecting a String field to be an empty string by default. Reference fields default to null, so calling name.length() on an unset field throws NullPointerException. Initialize fields explicitly in the constructor and this whole bug family disappears.

Scope: what can see your variable

Scope is the region of code where a name is visible. Java's rule is simple: a local variable exists from its declaration to the closing brace of the block it was declared in.

public class ScopeDemo {
    public static void main(String[] args) {
        int outer = 1;                    // visible until end of main

        for (int i = 0; i < 3; i++) {     // i visible only inside the loop
            int inner = i * 10;           // recreated each iteration
            System.out.println(outer + " " + i + " " + inner);
        }
        // System.out.println(i);         // compile error: i is out of scope

        if (outer == 1) {
            String message = "block scoped";
            System.out.println(message);
        }
        // message is gone here too
    }
}

Loop counters vanishing after the loop is a feature: it keeps names from leaking across your method. Declare variables in the smallest scope that works — it shrinks the amount of code you must read to understand any one of them. Scope interacts constantly with the if/switch blocks covered in Java control statements.

Shadowing and this

A parameter may share a field's name, in which case the parameter shadows the field inside the method. this. reaches the field explicitly — the pattern you will see in nearly every constructor and setter:

public class Course {
    private String title;

    public Course(String title) {
        this.title = title;   // field = parameter
    }
}

Without this., the line title = title; assigns the parameter to itself and the field stays null — a classic silent bug that IDEs flag as a warning.

final variables and constants

Marking a variable final means single assignment: once set, it cannot be re-assigned.

final double GST_RATE = 0.18;
// GST_RATE = 0.20;              // compile error

static final int MAX_LOGIN_ATTEMPTS = 3;   // the standard constant pattern

For reference types, final locks the reference, not the object: a final List cannot be repointed at another list, but you can still add elements to it. True constants in Java are static final with UPPER_SNAKE_CASE names — one shared, immutable value per class.

Use final liberally on local variables that never change. It costs nothing and tells every reader "this value is settled" — a habit that pays off when your methods grow and when values feed into the expressions you will build with Java operators.

Putting it together

The mental checklist for any variable you write:

  1. Type — pick the right one from the primitives and references you know.
  2. Kind — local for temporary work, instance for per-object state, static for class-wide state (rare; think before using).
  3. Scope — declare as late and as locally as possible.
  4. Initialization — fields in the constructor, locals at declaration.
  5. Mutabilityfinal unless it genuinely needs to change.

Next in the series: Java operators, where these variables start doing arithmetic, comparisons and logic — the raw material of every program you will write from here on.

Frequently Asked Questions

What are the three types of variables in Java?
Local variables are declared inside a method and exist only while that method runs. Instance variables are declared in a class without static, and every object gets its own copy. Static variables are declared with the static keyword, and a single copy is shared by all objects of the class.
Do Java variables have default values?
Instance and static variables do: 0 for numeric types, false for boolean and null for references. Local variables do not — the compiler refuses to let you read a local variable before you assign it, which prevents garbage-value bugs.
What is variable scope in Java?
Scope is the region of code where a variable is visible. A local variable is visible from its declaration to the end of the enclosing block, an instance variable is visible throughout the object, and a static variable is visible wherever the class is accessible.
What does the final keyword do to a variable?
final means the variable can be assigned exactly once. For primitives the value can never change; for references the variable cannot point to a different object, though the object itself may still be modified. Constants combine static and final, like static final int MAX_RETRIES = 3.
What is var in Java and when should I use it?
Since Java 10, var lets the compiler infer a local variable's type from the initializer, so var list = new ArrayList<String>() works. It is still fully static typing, only with less repetition. Use it when the type is obvious from the right-hand side; avoid it when it hurts readability.
Can two variables have the same name in Java?
Yes, in different scopes. A local variable or parameter can share a name with an instance variable, and the local one shadows it inside the method. That is why constructors use this.name = name to distinguish the field from the parameter.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 14 July 2026 LinkedIn
Chat with us