Topic 17 of 119 2. Fundamentals of Java Programming Interactive Tutorial

Java Variables: Declaration, Initialization, Scope, and Different Forms

16 mins read Last updated: 22 Aug 2026 17,941 views

Direct Answer & Core Concept

Java has three main kinds of variable based on where you declare them. Local variables sit inside a method or block, exist only while that code runs, and have no default value, so the compiler forces you to initialize them before use. Instance variables are declared in the class body without static, so every object gets its own copy, and they receive Java default values such as 0, false or null automatically. Static variables are declared with static, and exactly one copy is shared by the whole class no matter how many objects exist. On top of those three, method parameters, final constants and the var type inference keyword give you even more practical forms.

Detailed Explanation & Mechanics

1. What Is a Variable in Java?

A variable is a named box that holds a value while your program runs. You give it a type, a name, and then you put data inside it. Reading the value back later is how your program remembers things.

Main.java
Run Online
int customerAge = 25;
// type + name + value

The three parts have distinct jobs. The type such as int or String decides what kind of data can go inside and how much memory it needs. The name is what you call it, so it must follow identifier rules. The value is the actual data stored at that moment.

Architecture Diagram
HOW A VARIABLE IS CREATED

    ┌──────────────────────────────────────────────┐
    │   TYPE      int            how much, which  │
    │   NAME      customerAge    how you refer to│
    │   VALUE     25             the real data    │
    └──────────────────────────────────────────────┘

  Change the type later  ──►  not allowed, the box is fixed
  Change the value later ──►  always allowed, that is the point

The idea of a fixed box is what makes Java strongly typed. A box declared as int can hold whole numbers only, and the compiler will stop you before your program runs if you try to store text in it.

2. Where Can You Declare a Variable in Java?

The place you declare a variable decides almost everything about it: how long it lives, who can see it, whether it has a default value, and where it is stored in memory.

KindDeclared WhereLives ForDefault Value
Local variableInside a method or blockUntil the block endsNone, must initialize
Instance variableInside the class body, no staticAs long as the object exists0, false, null
Static variableInside the class body, with staticAs long as the class is loaded0, false, null
Method parameterIn the method signatureUntil the method returnsMust receive a value
Constructor parameterIn the constructor signatureUntil the constructor endsMust receive a value
ConstantWith static finalAs long as the class is loadedMust be given a value
Main.java
Run Online
THE SAME DECLARED IN THREE PLACES public class Order {
    static int orderCount = 0;
    //  static    -> ONE copy, shared
    String customerName;
    //  instance  -> one copy per object
    void place() {
        int quantity = 2;
        //  local     -> lives only in this block
    }
}

3. Local Variables

A local variable is declared inside a method body, a constructor body, or any block between braces. It is the most common variable you will write and the easiest to reason about, because it simply stops existing when the block ends.

  • You must initialize a local variable before you read it, or the compiler refuses to build your program.
  • Two local variables with the same name can exist in two different methods, or even two different blocks, without any conflict.
  • A local variable is not visible to any other method or class.
  • Its scope begins at the declaration line and ends at the closing brace.
Main.java
Run Online
public class LocalVariableDemo {
    public static void main(String[] args) {
        int marks = 88;
        // declared and initialized together
        String grade;
        grade = "B";
        // initialized later, still fine
{
            int marks = 50;
            // a NEW variable, this block only
            System.out.println("inner marks = " + marks);
        } System.out.println("outer marks = " + marks + ", grade = " + grade);
    }
}

The inner marks above is a completely separate variable. Java allows it because the inner one is not visible outside its own block, and that is exactly what people mean when they talk about scope.

4. Instance Variables, Also Called Member or Field Variables

An instance variable is declared directly inside the class body, outside every method. Each object built from that class gets its own private copy of every instance variable.

  • They are created when you use new to build an object, and disappear when that object is no longer referenced.
  • You can read or write them through the this keyword to be explicit about which object you mean.
  • They do not need to be initialized, because Java assigns a sensible default.
  • They are the state of an object, which is why most real Java classes are built around them.
Main.java
Run Online
public class Student {
    int rollNumber;
    // no modifier needed to declare a field
    String name;
    double percentage;
    boolean isPassed;
    public void promote() {
        this.percentage = this.percentage + 5;
        // this marks the current object
        if (this.percentage >= 40) {
            this.isPassed = true;
        }
    } public static void main(String[] args) {
        Student first = new Student();
        first.rollNumber = 7;
        first.name = "Tanmoy";
        first.percentage = 38;
        first.promote();
        System.out.println(first.name + " -> " + first.percentage + ", passed = " + first.isPassed);
    }
}

5. Static Variables, Also Called Class Variables

A static variable is declared with the static keyword inside the class body. There is exactly one copy of it, created when the class loads, and every object of that class shares it.

  • Use static for state that genuinely belongs to the whole class, such as counters, configuration, and caches.
  • Access it through the class name rather than an object, because that is clearer and avoids confusion: ClassName.counter.
  • Changing a static value changes it for every object at once.
  • Because shared state is harder to test and reason about, use static sparingly.
Main.java
Run Online
public class Account {
    private static int nextAccountNumber = 1000;
    // one copy for all accounts
    private final int accountNumber;
    private double balance;
    public Account() {
        accountNumber = ++nextAccountNumber;
        // unique per object
        balance = 0;
    } public int getAccountNumber() {
        return accountNumber;
    } public static void main(String[] args) {
        Account a = new Account();
        Account b = new Account();
        Account c = new Account();
        System.out.println(a.getAccountNumber() + " " + b.getAccountNumber() + " " + c.getAccountNumber());
        // 1001 1002 1003
        System.out.println("counter is now " + Account.nextAccountNumber);
    }
}

Try removing the static keyword from nextAccountNumber and the program stops compiling, because a non-static field cannot be reached from a static context. That single keyword is what turns a field into a shared counter.

6. Method Parameters and Constructor Parameters

Parameters are variables written inside the parentheses of a method or constructor signature. They behave like local variables: they exist only while that method runs, and they are given a value by the caller.

Main.java
Run Online
public class Rectangle {
    private double length;
    private double width;
    // Constructor parameters are assigned to fields
    public Rectangle(double length, double width) {
        this.length = length;
        // this.length = field, length = parameter
        this.width = width;
    } // Method parameters are used to compute a result
    public double area(double scaleFactor) {
        return length * width * scaleFactor;
    }
}

Important: Java always passes arguments by value. For an int the value is copied. For an object the reference is copied, which means both variables point at the same object.

Main.java
Run Online
static void modify(StringBuilder builder) {
    builder.append("-changed");
    // same object, caller sees the change
}static void reassign(StringBuilder builder) {
    builder = new StringBuilder("-new");
    // only the parameter changes
}
  • Mutating an object passed in is visible to the caller.
  • Reassigning the parameter inside the method is not, which surprises almost everyone at first.

7. Declaration and Initialization: Four Ways You Will See

Java lets you declare and initialize in several slightly different ways, and beginners meet all four quickly.

Main.java
Run Online
FOUR COMMON WAYS TO DECLARE AND INITIALIZE A) DECLARE AND INITIALIZE IN ONE STEP int marks = 88;
B) DECLARE FIRST, INITIALIZE LATER int marks;
marks = 88;
C) SEVERAL NAMES OF THE SAME TYPE int x, y, z;
x = 1;
y = 2;
z = 3;
D) FINAL OR INFERRED final int limit = 100;
var price = 249.99;
Main.java
Run Online
public class DeclarationForms {
    static final double GST_RATE = 0.18;
    // constant at class level
    int instanceValue = 42;
    // instance with a value
    public int compute(int input, int bonus) {
        int result = input + bonus;
        // local, one step
        int step1, step2;
        // local, two names
        step1 = result * 2;
        step2 = result * 3;
        var shortcut = step1 + step2;
        // var infers int
        return(int)(shortcut *(1 + GST_RATE));
    }
}
  • You may declare several variables of one type in a single statement, but only the last one can be initialized inline.
  • A final variable must be initialized exactly once, either inline or in the constructor.
  • Assigning a different type later is a compile error, even between compatible numeric types. The explicit cast is required.

8. Default Values: Why Locals and Fields Behave Differently

This is the detail that surprises new Java programmers most. A field can be used without ever being assigned, but a local variable cannot.

TypeDefault Value
byte, short, int0
long0L
float0.0f
double0.0d
charthe null character
booleanfalse
String, arrays, your own classesnull
Main.java
Run Online
public class DefaultValueDemo {
    static int staticNumber;
    int instanceNumber;
    String text;
    int[] numbers;
    public static void main(String[] args) {
        DefaultValueDemo d = new DefaultValueDemo();
        System.out.println("staticNumber  = " + staticNumber);
        // 0
        System.out.println("instanceNumber= " + d.instanceNumber);
        // 0
        System.out.println("text          = " + d.text);
        // null
        System.out.println("numbers[2]    = " + d.numbers[2]);
        // null
        int localNumber;
        // ERROR: must be initialized first
        // localNumber = 5;
    }
}

The reasoning behind this design is sound. A field always belongs to an object that already exists, so filling in a neutral default is safe. A local variable is used immediately after you write it, so the compiler refuses to invent a value you never meant.

9. Scope: Where a Variable Is Visible

Java scopes go from widest to narrowest: class level, then instance level, then block level. When the same name exists in more than one level, the narrowest one wins, and the wider one is said to be shadowed.

Architecture Diagram
SCOPE FROM WIDEST TO NARROWEST

  ┌──────────────────────────────────────────────────┐
  │ CLASS LEVEL      static int value = 1;           │
  │  ┌────────────────────────────────────────────┐  │
  │  │ INSTANCE LEVEL   int value = 2;            │  │
  │  │  ┌──────────────────────────────────────┐   │  │
  │  │  │ BLOCK LEVEL   int value = 3;         │   │  │
  │  │  │  inside here, value is 3              │   │  │
  │  │  └──────────────────────────────────────┘   │  │
  │  │  back in the method, value is 2            │  │
  │  └────────────────────────────────────────────┘  │
  │  this.value reaches the instance variable        │
  └──────────────────────────────────────────────────┘
Main.java
Run Online
public class ShadowingDemo {
    static int value = 1;
    // class level
    int value = 2;
    // instance level
    public void show() {
        System.out.println(value);
        // 2, instance wins here
        if (true) {
            int value = 3;
            // block level, shadows both
            System.out.println(value);
            // 3
        } System.out.println(value);
        // 2 again
        System.out.println(ShadowingDemo.value);
        // 1, fully qualified
    }
}

Shadowing is legal but confusing, which is why most style guides advise against naming a local variable the same as a field.

10. final Variables and Constants

The final keyword means a variable can be assigned exactly once. After that, the compiler rejects any further change, which is how Java expresses immutability.

  • A final local variable must be initialized exactly once, at declaration or later in the same block.
  • A final parameter cannot be reassigned inside the method.
  • A static final field is the standard way to write a constant in Java.
  • A final reference does not freeze the object it points at, only the reference itself.
Main.java
Run Online
public class Constants {
    static final double GST_RATE = 0.18;
    // a real constant
    static final String DEFAULT_CURRENCY;
    final int invoiceId;
    // blank final, set in constructor
    static {
        DEFAULT_CURRENCY = "INR";
        // static initializer block
    } public Constants(int invoiceId) {
        this.invoiceId = invoiceId;
    } public void tryToChange() {
        // GST_RATE = 0.20;                    // ERROR: final cannot be reassigned
        final int discount = 10;
        // final, so it can never change
        // discount = 20;                     // ERROR: final cannot be reassigned
        // discount = discount - 1;           // ERROR: still a reassignment
        int price = 100;
        // not final, so this is fine
        price = price - 1;
        // a reassignment, and perfectly legal
    }
}

Writing the name of a constant in UPPER_SNAKE_CASE is a convention rather than a rule, but it is followed everywhere in professional Java, and it is what makes constants instantly recognisable while you read.

11. var: Local Variable Type Inference

From Java 10 onwards you can write var instead of a type, and the compiler works out the type from the value you assign on the same line.

  • var works only for local variables, never for fields, method return types or parameters.
  • The value must be on the same statement, because there is nothing else to infer from.
  • The variable is still strongly typed. Once inferred, var behaves exactly like the real type and cannot later change.
  • Use it when the type is obvious from the right-hand side. Do not use it when it hides the type from a reader.
Main.java
Run Online
import java.util.ArrayList;
public class VarDemo {
    public static void main(String[] args) {
        var count = 10;
        // inferred as int
        var price = 249.99;
        // inferred as double
        var name = "Java";
        // inferred as String
        var marks = new ArrayList();
        // inferred as ArrayList
        System.out.println(count + " " + price + " " + name);
        System.out.println(marks.isEmpty());
        // var total;                     // ERROR: var needs an initializer
        // var total = null;              // ERROR: nothing to infer from
        // var data = {1, 2, 3};          // ERROR: array initializers not allowed
    }
}

12. Where Variables Live in Memory

Understanding memory is not required to write Java, but it explains why local variables vanish so quickly and why objects behave differently.

Architecture Diagram
MEMORY LAYOUT AT A GLANCE

  ┌─────────────────────────── STACK ────────────────────────────┐
  │  main() frame          addNumbers() frame                     │
  │  ┌────────────────┐     ┌────────────────┐                   │
  │  │ int a = 5      │     │ int sum = 15   │  local variables   │
  │  │ int b = 10     │     │ int limit = 100│  and parameters    │
  │  └────────────────┘     └────────────────┘                   │
  │  lives while the method runs, then disappears                │
  └───────────────────────────────────────────────────────────────┘
              │ references point down
              v
  ┌─────────────────────────── HEAP ─────────────────────────────┐
  │  Account object A        Account object B       static field │
  │  ┌──────────────────┐    ┌──────────────────┐    ┌──────────┐ │
  │  │ accountNumber 7  │    │ accountNumber 8  │    │ nextId 9 │ │
  │  │ balance 500.00   │    │ balance 250.00   │    └──────────┘ │
  │  └──────────────────┘    └──────────────────┘   ONE shared   │
  │  objects survive until nothing references them                │
  └───────────────────────────────────────────────────────────────┘
  • Local variables and method parameters live in the stack frame of the calling method, and disappear when the method returns.
  • Objects created with new live on the heap, together with their instance variables.
  • Static fields hold one value per class, created when the class is first loaded and freed when the class is unloaded.
  • This is why passing an object shares its contents, while reassigning a local variable never affects anyone else.

13. Common Variable Errors and How to Fix Them

These are the compile-time errors every Java beginner meets at least once.

What You WroteCompiler SaysHow To Fix It
int total; System.out.println(total);variable total might not have been initializedAssign it first, such as int total = 0;
int x = "hello";incompatible types: String cannot be converted to intUse a String variable
static void f() { count++; }non-static variable count cannot be referenced from a static contextMake the field static or move the code into an instance method
final double RATE = 0.1; RATE = 0.2;cannot assign a value to final variable RATERemove final or declare a new variable
String s; s.length();NullPointerException at runtimeInitialize it, because the default is null
int sum = 5; sum = "ten";String cannot be converted to intChange the value, not the type of the box
  • A NullPointerException is the one error you will meet at runtime rather than at compile time, and it always means a reference was never given a value.
  • Reading an uninitialized array element is also null or 0, because arrays are objects with their own defaults.
  • Assigning an int to a long variable fails, even though it feels safe. The correct move is an explicit cast such as long bigger = (long) smallNumber.

14. Java Variables Cheat Sheet

Keep this table nearby while you write your first few programs.

QuestionAnswer
Local variables must be initialized?Yes, before first use
Instance variables need initialization?No, they get 0, false or null
Static variables exist how many times?Once per class, shared by all objects
Where do local variables live?In the stack frame of the method
Where do instance variables live?Inside the object, on the heap
Is Java passed by value or reference?Always by value, including references
What does final mean?Assigned exactly once
How do I write a constant?static final, with UPPER_SNAKE_CASE naming
Can var be used for fields?No, only for local variables with an initializer
What is shadowing?A narrower variable hides a wider one of the same name

With these ten answers memorised, the next topic, Java data types, becomes easy, because you now know where a value is stored and what it defaults to before you even choose its type.

Runnable Code Example: Java Variables

Java 17+
Main.java
Run Online
public class VariablesDemo {
    //
    1. Static(class) variable - one shared copy for the whole class static int objectCount = 0;
    //
    2. Instance variables - every object gets its own copy int instanceId = 101;
    String customerName;
    boolean isActive;
    double balance;
    //
    3. A constant - static plus final means one value for everyone static final double TAX_RATE = 0.18;
    public VariablesDemo(String customerName) {
        objectCount++;
        // every new object bumps the counter
        this.customerName = customerName;
    } public double applyTax(double amount) {
        //
        4. Method parameters - copies of the values the caller passed in double tax = amount * TAX_RATE;
        double payable = amount + tax;
        //
        5. Local variables - must be initialized before use String receipt = "RCPT-" + instanceId;
        double rounded = Math.round(payable * 100) / 100.0;
        //
        6. var lets the compiler infer the type(Java 10+) var format = "receipt=" + receipt;
        System.out.println(format + " payable=" + rounded);
        return rounded;
    } public static void main(String[] args) {
        VariablesDemo first = new VariablesDemo("tanmoy");
        VariablesDemo second = new VariablesDemo("priya");
        // Instance fields that were never assigned show their default values
        System.out.println("name=" + first.customerName + " (assigned in constructor)");
        System.out.println("isActive=" + first.isActive + " (default false)");
        System.out.println("balance=" + first.balance + " (default 0.0)");
        System.out.println("static counter=" + VariablesDemo.objectCount + " (shared)");
        System.out.println("tax on 1000 = " + first.applyTax(1000));
        // Local variables must be initialized first
        int discount = 50;
        // declaration plus initialization
        int shipping;
        // declaration only
        shipping = 25;
        // initialization later
        System.out.println("discount=" + discount + " shipping=" + shipping);
    }
}

Common Java Technical Interview Questions & Answers

Interview Prep
Q1

What are the three main kinds of variables in Java?

Local variables declared inside a method or block, instance variables declared in the class body without static, and static variables declared with static. Method parameters are a fourth practical form that behaves like a local variable.
Q2

Why must I initialize a local variable before using it?

Because local variables have no default value. The compiler cannot know what value you intend, so using an uninitialized local variable is a compile-time error. This forces you to think about every value you read.
Q3

Why do instance variables get default values but local variables do not?

An instance variable belongs to an object that already exists by the time it is read, so the language fills in a harmless default. A local variable lives inside a method where the compiler can prove exactly when it is first used, so it refuses to guess.
Q4

What are the default values of Java instance variables?

byte, short, int and long are 0; float is 0.0f; double is 0.0d; char is the null character; boolean is false; and every reference type such as String, arrays and your own objects starts as null.
Q5

What is the difference between a static variable and an instance variable?

An instance variable exists once per object, so ten objects hold ten separate copies. A static variable exists once per class, is created when the class loads, and is shared by every object of that type. Changing a static value changes it for everybody.
Q6

Are Java variables passed by value or by reference?

Always by value. When you pass an object, Java copies the reference value, so both variables point at the same object and changes made through one are visible through the other. Reassigning the parameter itself, however, affects only the parameter.
Q7

What does final mean for a variable?

A final variable can be assigned exactly once. A final local variable or parameter becomes effectively immutable, and a static final variable is the standard way to declare a constant in Java.
Q8

Can I declare a final variable without giving it a value right away?

Yes, that is called a blank final. You must give it a value exactly once before the constructor finishes, and for static fields the value must be assigned in a static initializer block.
Q9

Can I use var in Java?

Yes, from Java 10 onwards, but only for local variables. The compiler infers the type from the value you assign, and var cannot be used for fields, method return types or parameters without an initializer.
Q10

Where do local variables and instance variables live in memory?

Local variables and their primitive values live in the stack frame of the method call, while the objects themselves and their instance variables live on the heap. Static variables hold a single copy that exists for as long as the class is loaded.
Q11

Why does my local variable shadow my field?

Because the nearest declaration wins. Java looks for the smallest scope first, so a local variable with the same name hides the instance variable inside that block, which is why this reference is often needed to reach the field.

Key Takeaways, Best Practices & Clean Code Rules

Java Best Practice & Production Rules

Declare each variable as close as possible to the place you first use it, because a short scope means fewer bugs and easier refactoring. Always give instance variables explicit initial values even though Java supplies defaults, since defaults like 0 or null rarely express real intent and hide uninitialised-state bugs. Use final for anything that should not change after construction, which makes objects safer to share. Reserve static for genuinely shared state such as configuration values and counters, because static state is shared, hard to test and survives every object. Avoid reusing the same name for a local variable and a field, since shadowing forces readers to check which one they are looking at. Prefer clear names over short ones, and when you find yourself needing several variables of the same type, remember that Java lets you declare them together.
We value your privacy & transparency

OperateTools uses cookies and local storage to ensure basic tool functionality, preserve preferences, and analyze aggregated traffic. We never sell your personal data or index your document files. Learn more in our Privacy Policy.