Skip to content
Ameen Abozaid
PublishedBEG-020-L05

static: belonging to the class

  • Lesson 5 of 7
  • 12 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

Until now every field and method belonged to an object: two accounts, two balances. But some things do not belong to any single account. How many accounts exist? What is the smallest amount you may deposit? Is a given account number valid? These questions are about the class as a whole, and that is where static comes in.

In the blueprint picture, an instance field is a feature of one particular house, such as its paint colour. A static member is written on the architect's drawing itself and shared by every house built from it, such as the drawing's reference number.

Why this matters: choosing between instance and static is one of the most frequent design decisions in Java. Beginners tend to make everything static to avoid thinking about objects, and that breaks the whole point of this module. By the end of the lesson you will have a rule to decide.

This lesson builds on Lessons 1 to 4 and on the earlier module where you wrote static methods and main.

Learning Objectives

By the end of this lesson you will be able to:

  • Explain the difference between instance members and static members.
  • Write a static field, a static final constant, and a static method.
  • Reach static members through the class name.
  • Explain why a static method cannot use instance fields directly, and read the compiler error.
  • Use a static counter to count the objects created.
  • Decide whether a given field or method should be static.

Written Explanation

Instance versus static

Instance memberStatic member
Belongs toOne objectThe class
How many copiesOne per objectOne in total, shared
Reached withobject.memberClassName.member
Needs an object to exist?YesNo
Has this?YesNo

So far, balance has been an instance field: ten accounts, ten balances. The Java tutorial calls a static field a class variable. Each object has its own id, for instance, while a single shared field keeps count of how many objects exist.

A static field: a shared counter

java
public class Account {
    static int count = 0;       // one copy, shared by every Account

    String owner;
    String number;
    double balance;

    Account(String owner, String number, double balance) {
        this.owner = owner;
        this.number = number;
        this.balance = balance;
        count++;                // runs for each new account
    }
}

Every time any constructor runs, it increments the same count. Outside the class, you read it through the class name:

java
System.out.println(Account.count);   // 0, before any account exists

Note the 0 before any object exists. A static field exists as soon as the class is loaded, with no object needed. Java also lets you write ana.count, but the tutorial advises against it, because it hides that count is not about ana. Always use Account.count.

A static final constant

When a value is shared and must never change, combine static with final:

java
static final double MIN_DEPOSIT = 0.01;

final means the variable cannot be reassigned after it gets its value, and the compiler enforces it:

text
Bad2.java:3: error: cannot assign a value to static final variable MIN_DEPOSIT
        Account.MIN_DEPOSIT = 5;
               ^

By convention, constant names use upper-case letters with underscores between words. Constants are static because one copy for the whole class is enough: it makes no sense for every account to store its own MIN_DEPOSIT. You already know a constant from the standard library, Math.PI.

A static method

A static method is called on the class and does not need an object:

java
static int getCount() {
    return count;
}

static boolean isValidNumber(String number) {
    return number != null && number.startsWith("A-");
}
java
Account.getCount();
Account.isValidNumber("A-9");     // true

You have used this form all along: Math.max(3, 5) is a static method of Math, and your own main is static.

The big restriction

Static members are shared, so a static method has no current object. It has no this, and it cannot read instance fields or call instance methods directly. The tutorial summarizes the rules:

  • Instance methods can use instance members and static members.
  • Static methods can use static members only. To use an instance member, they need an object reference.

Here is what the compiler says when you break the rule:

java
public class Bad {
    double balance = 5;
    static double show() {
        return balance;          // which object's balance?
    }
}
text
Bad.java:4: error: non-static variable balance cannot be referenced from a static context
        return balance;
               ^

The message is the question "which object's balance?" in compiler words. If the method really needs one object's data, it should not be static. The error will also appear if you call an instance method such as deposit from main without an object, which is why you need new first. The usual (wrong) cure for this error is to add static to the field or method, and then the problem moves elsewhere. Think about what the member belongs to.

Rule of thumb: when is it static?

Ask: is it about one particular object, or about the class as a whole?

  • Depends on one object's state (balance, deposit, describe): instance.
  • Same for all objects, or needs no object (count, MIN_DEPOSIT, isValidNumber): static.
  • When in doubt, start with instance. A class where everything is static is just a bag of global variables and functions, and it throws away what objects offer: separate state per object.

Examples

Example 1: counting objects (simple)

java
public class Main {
    public static void main(String[] args) {
        System.out.println(Account.getCount());
        Account a = new Account("Ana", "A-1", 0);
        Account b = new Account("Omar", "A-2", 0);
        System.out.println(Account.count + " " + a.deposit(0) + " " + b.deposit(5));
        System.out.println(Account.isValidNumber("A-9") + " " + Account.isValidNumber("X1"));
    }
}

Using the Account of this lesson (fields, a constructor that does count++, deposit that refuses amounts below MIN_DEPOSIT and returns a boolean, and the two static methods above), the output on JDK 21 is:

text
0
2 false true
true false

Before any new, the count is 0. Two objects later it is 2. deposit(0) returns false because 0 is below MIN_DEPOSIT; deposit(5) returns true. The instance method deposit uses the static constant directly, which is allowed in that direction.

Example 2: a product limit as a constant (practical)

A shop never allows more than 1000 items of one product, and wants to know how many products were created:

java
public class Product {
    static int created = 0;
    static final int MAX_STOCK = 1000;

    String name;
    int stock;

    Product(String name, int stock) {
        this.name = name;
        this.stock = Math.min(stock, MAX_STOCK);
        created++;
    }

    static int getCreated() {
        return created;
    }

    boolean isFull() {
        return stock == MAX_STOCK;
    }
}
java
Product a = new Product("Tea", 40);
Product b = new Product("Mug", 5000);
System.out.println(Product.getCreated() + " " + a.isFull() + " " + b.isFull() + " " + b.stock);

Output:

text
2 false true 1000

The limit lives in one place: if the shop changes it to 2000, only the constant changes. The constructor uses Math.min, a static method you already know. isFull is an instance method because "full" depends on this product's own stock.

Example 3: static used by mistake (realistic)

A learner is tired of non-static errors and makes balance static as well. In the small bank program you will build in the next lesson (two accounts, Ana with 100 and Omar with 0, then deposits of 50 and 20), changing the field to static double balance; makes the output:

text
Ana (A-1): 70.0
Omar (A-2): 70.0
Second withdrawal ok? false
Accounts created: 2

Ana had 100 plus 50 and Omar 0 plus 20, but both show 70.0. There is only one balance, shared by all accounts, so each new account's constructor overwrote it, and each deposit changed everybody's balance. This is the signature symptom of a field that should be an instance field: values that change together across objects that should be independent. The fix is to delete static from balance, and the program prints 150.0 for Ana and 20.0 for Omar again. Lesson 7 shows how to see this in a debugger.

Backend Insight

Static members appear in backend code in a few specific roles: constants (such as the name of a configuration key, or a maximum page size), utility methods that take everything they need as parameters (for formatting or validation), and a few shared counters or identifiers. Business data, such as an order's total or a customer's address, is never static, because a server handles many orders and customers at the same time.

There is one more reason to be careful. A mutable static field is shared by every request your server processes. Many requests can run at once, and they all touch that same field. Such shared state can produce unpredictable results, and it is one of the classic sources of hard-to-reproduce bugs. A constant (static final) is safe because it never changes, but a shared counter that many threads update needs extra care that you will learn later. For now, use mutable statics only in simple, single-threaded programs like this module's labs.

Common Mistakes

Mistake 1: Making everything static

The compiler error "non-static ... cannot be referenced from a static context" tempts learners to add static everywhere. This compiles, but all objects now share their data. Fix the cause: create an object and call the method on it.

Mistake 2: Using a static method for something that needs one object's state

static boolean withdraw(double amount) cannot know whose balance to change. If the method depends on an object's fields, it is an instance method.

Mistake 3: Reaching a static member through an object

ana.count compiles but suggests that the count belongs to ana. Write Account.count.

Mistake 4: Forgetting final on a constant

static double MIN_DEPOSIT = 0.01; can be changed from anywhere, and a stray assignment will silently alter the rule for the whole program. Add final.

Mistake 5: Expecting a static counter to reset

The static field lives as long as the program runs. Creating more objects keeps increasing count. It never goes down when objects stop being used, unless your code decrements it.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. What is the difference between how many copies of an instance field exist and how many of a static field?

Show solution A1

A1. An instance field has one copy per object (ten objects, ten copies). A static field has exactly one copy for the whole class, shared by every object.

A2. How do you read the static field created of class Product from main?

Show solution A2

A2. Product.created. Using the class name is the recommended form.

A3. Why can the compiler refuse static double show() { return balance; } when balance is an instance field?

Show solution A3

A3. A static method has no current object, so "which object's balance?" has no answer. The compiler reports that a non-static variable cannot be referenced from a static context. The method should be an instance method (or take a Product or Account parameter).

Level B: Application

B1. Classify each as instance or static, and justify: (a) the name of a product, (b) the sales tax rate used by every product, (c) a method that checks whether a string looks like a product code, (d) a method that returns the product's name in capital letters.

Show solution B1

B1. (a) Instance: each product has its own name. (b) Static, and final if it never changes: one value for all products. (c) Static: the check uses only its string parameter and no product's data. (d) Instance: it uses this product's name.

B2. Add to your Product a static counter created and a static method getCreated(). Create three products and print the counter before and after.

Show solution B2

B2.

java
static int created = 0;

Product(String name, int stock) {
    this.name = name;
    this.stock = stock;
    created++;
}

static int getCreated() {
    return created;
}
java
System.out.println(Product.getCreated());   // 0
new Product("A", 1);
new Product("B", 2);
new Product("C", 3);
System.out.println(Product.getCreated());   // 3

B3. Make MAX_STOCK a constant and use it so that a new product's stock is never above it. Say what error appears if someone tries Product.MAX_STOCK = 5;.

Show solution B3

B3.

java
static final int MAX_STOCK = 1000;
// in the constructor:
this.stock = Math.min(stock, MAX_STOCK);

Product.MAX_STOCK = 5; gives a compile error of the form cannot assign a value to static final variable MAX_STOCK.

Level C: Challenge

C1. A learner writes an Order class where total is static, then creates two orders with different totals and finds that both print the same total. Explain what happened and how to fix it.

Show solution C1

C1. total is shared by the whole class, so there is only one total. Creating the second order overwrites it, and both objects read the same variable. Fix: remove static so that each order has its own total.

C2. Give each new Account a unique id by using a static counter, so the first account gets 1, the second 2, and so on. Write the field and constructor lines. Explain why id itself must be an instance field.

Show solution C2

C2.

java
static int nextId = 1;
int id;

Account(String owner, String number, double balance) {
    this.id = nextId;
    nextId++;
    // ... other assignments
}

The first account gets 1, the second 2. The counter nextId is static because it must be shared to know what comes next. id is an instance field because each account needs its own, different, id.

Mini Challenge

Give your own class a static counter and a static final constant, and a static helper method that needs no object (for example a validity check on a string). Then:

  1. Create four objects and print the counter through the class name.
  2. Use the constant inside one instance method and show the effect.
  3. Try to use an instance field inside the static helper, read the compiler message, and fix it by passing the value in as a parameter.
  4. Briefly justify, in a comment above each member, why it is static or instance.

Check your work: every static member is accessed with the class name, and no data that differs between objects is static.

Summary & Next Lesson

Key takeaways

  • Instance members belong to each object; static members belong to the class, with one shared copy.
  • Reach static members with the class name (Account.count), not with an object variable.
  • static final makes a constant. By convention it is written in upper case with underscores.
  • A static method has no this and cannot use instance fields or methods directly; the compiler reports a non-static member referenced from a static context.
  • Rule of thumb: if it depends on one object's state, it is not static. Do not make everything static.

Next lesson

You have everything for the lab: fields, constructors, methods, this, objects, and static. The next lesson, "Demo: Bank Accounts v1 from an empty file", builds the Account class and a small main step by step, including the planned shadowing mistake.

Self-check

  1. How many copies of a static field exist if you create 100 objects?
  2. How do you call a static method getCount() of Account?
  3. Why can a static method not read balance directly?
  4. What does static final mean?
  5. Which should be static: an account's owner, or the minimum deposit for all accounts?
Show answers
  1. One.
  2. Account.getCount().
  3. It has no current object, so it cannot know which object's balance to read; it needs an object reference.
  4. One shared copy that cannot be reassigned: a constant.
  5. The minimum deposit. The owner differs per account, so it is an instance field.

References

  • Oracle, The Java Tutorials, Understanding Class Members. Supports: class variables are shared by all instances; they are reached through the class name (via an object is discouraged); static methods cannot access instance members or use this; static final defines a constant with an upper-case name by convention.
  • Oracle, The Java Tutorials, Creating Objects. Supports: new invokes the constructor, which is where our counter increments.
  • Compiler messages and program output come from compiling and running the code on JDK 21 (javac 21.0.10). The warning about shared mutable static state in a server is general engineering advice that we did not tie to a specific source.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.