Static Members
IB Syllabus: B3.1 – Distinguish between static and instance members.
Table of Contents
- Key Concepts
- Worked Examples
- Quick Check
- Trace Exercise
- Spot the Error
- Predict the Output
- Practice Exercises
- Connections
Key Concepts
Instance vs Static – The Core Difference
Everything in a class is either instance (belongs to each object) or static (belongs to the class itself).
| Instance | Static | |
|---|---|---|
| Belongs to | Each individual object | The class itself |
| How many copies? | One per object | Exactly one, shared by all objects |
| Accessed via | Object reference: obj.method() | Class name: ClassName.method() |
| Can access | Instance + static members | Static members only |
Has this? | Yes | No |
Static Variables
A static variable (also called a class variable) is shared by all objects of the class. There is only one copy, regardless of how many objects exist. If one object changes it, all objects see the change.
The most common use: counting how many objects have been created.
public class Student {
private String name;
private static int count = 0; // shared by ALL Student objects
public Student(String name) {
this.name = name;
count++; // every new Student increments the same counter
}
public String getName() { return name; }
public static int getCount() { return count; }
}
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
Student s3 = new Student("Charlie");
System.out.println(Student.getCount()); // 3
System.out.println(s1.getName()); // Alice
count is shared – there is one counter for the entire class, not one per student. name is instance – each student has their own.
Static Methods
A static method belongs to the class, not to any object. It is called using the class name, not an object reference. It cannot access instance variables or call instance methods because it has no this – there is no specific object it is operating on.
public class MathHelper {
public static int square(int n) {
return n * n;
}
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
}
// Called on the class, not on an object
int result = MathHelper.square(5); // 25
int bigger = MathHelper.max(3, 7); // 7
You already use static methods every day:
Math.random()– no Math object neededMath.sqrt(16)– the method belongs to the Math classInteger.parseInt("42")– converts a String to intSystem.out.println()–outis a static field ofSystem
Why main is Static
public static void main(String[] args)
main is static because it is the entry point of the program – it runs before any objects exist. If main were an instance method, Java would need an object to call it on, but no objects exist yet at program startup. Making it static means Java can call it directly on the class.
What Static Methods Cannot Do
A static method has no this reference. It cannot:
public class Student {
private String name;
private static int count = 0;
// This WON'T compile:
public static void printName() {
System.out.println(name); // ERROR -- which student's name?
System.out.println(this.name); // ERROR -- no 'this' in static context
}
// This WILL compile:
public static int getCount() {
return count; // OK -- count is static too
}
}
“Non-static variable cannot be referenced from a static context” is one of the most common Java compiler errors beginners encounter. It means you are trying to use an instance variable inside a static method. Either make the method non-static, or pass the object as a parameter.
Static Constants
Static variables combined with final create constants – values that are shared across all objects and can never be changed:
public class Circle {
public static final double PI = 3.14159265358979;
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getArea() {
return PI * radius * radius;
}
}
System.out.println(Circle.PI); // 3.14159265358979
// Circle.PI = 3.0; // ERROR -- final cannot be reassigned
PI is public because there is no harm in reading it (it never changes), static because it is the same for all circles, and final because its value is fixed.
When to Use Static
| Use static when… | Example |
|---|---|
| The data is shared by all objects | count of created objects |
| The method does not need any object’s data | Math.sqrt(), Integer.parseInt() |
| The value is a constant | Circle.PI, Integer.MAX_VALUE |
| The method is a utility/helper that operates only on its parameters | MathHelper.square(n) |
| Do NOT use static when… | Example |
|---|---|
| Each object needs its own copy | name, balance, grade |
| The method reads or modifies instance data | getBalance(), deposit() |
The method uses this | Any method referencing the current object |
Worked Examples
Example 1: Tracking Object Count
public class Order {
private static int nextId = 1; // shared counter
private int orderId; // unique per object
private String item;
public Order(String item) {
this.orderId = nextId; // assign current counter value
nextId++; // increment for next order
this.item = item;
}
public int getOrderId() { return orderId; }
public String getItem() { return item; }
public static int getNextId() { return nextId; }
}
Order o1 = new Order("Laptop");
Order o2 = new Order("Mouse");
Order o3 = new Order("Keyboard");
System.out.println(o1.getOrderId()); // 1
System.out.println(o2.getOrderId()); // 2
System.out.println(o3.getOrderId()); // 3
System.out.println(Order.getNextId()); // 4 (next available)
Each order gets a unique ID from the shared counter. The counter lives on the class, not on any individual order.
Example 2: Static Utility Method
public class StringHelper {
public static String reverse(String text) {
String result = "";
for (int i = text.length() - 1; i >= 0; i--) {
result = result + text.charAt(i);
}
return result;
}
public static boolean isPalindrome(String text) {
String lower = text.toLowerCase();
return lower.equals(reverse(lower));
}
}
System.out.println(StringHelper.reverse("hello")); // olleh
System.out.println(StringHelper.isPalindrome("racecar")); // true
System.out.println(StringHelper.isPalindrome("hello")); // false
No StringHelper object is ever created. The methods are called directly on the class because they operate only on their parameters – they do not need any object state.
Quick Check
Q1. How many copies of a static variable exist?
Q2. Why can't a static method access instance variables?
Q3. Why is main declared as static?
Q4. How do you call a static method?
Q5. Which of these should NOT be static in a BankAccount class?
Trace Exercise
Trace the Order class from Example 1. Track both the static nextId and each object’s instance orderId.
Trace: Static vs Instance
Order o1 = new Order("Laptop");
Order o2 = new Order("Mouse");
Order o3 = new Order("Keyboard");| After line | nextId (static) | o1.orderId | o2.orderId | o3.orderId |
|---|---|---|---|---|
| Before any objects | 1 | -- | -- | -- |
| After o1 = new Order("Laptop") | -- | -- | ||
| After o2 = new Order("Mouse") | -- | |||
| After o3 = new Order("Keyboard") |
Notice:
nextIdchanges every time the constructor runs (it is shared). EachorderIdis set once during construction and never changes (it is instance). This is the fundamental difference between static and instance.
Spot the Error
This code does not compile. Click the line with the error, then pick the fix.
Pick the fix:
Predict the Output
What does this print?
Student s1 = new Student("Alice");
Student s2 = new Student("Bob");
Student s3 = new Student("Charlie");
System.out.println(Student.getCount()); What does o1.getOrderId() print?
Order o1 = new Order("Laptop");
Order o2 = new Order("Mouse");
System.out.println(o1.getOrderId()); After creating both orders above, what does Order.getNextId() print?
Order o1 = new Order("Laptop");
Order o2 = new Order("Mouse");
System.out.println(Order.getNextId()); Practice Exercises
Core
- Static or instance? – For each of the following, state whether it should be static or instance, and explain why:
- A
Car’sspeed - A counter for total
Carobjects created - A method
getSpeed()that returns a car’s current speed - A method
getTotalCars()that returns how many cars exist - A constant
MAX_SPEED = 200
- A
- Add a counter – Take the
Productclass from the Encapsulation page. Add a statictotalProductsvariable that tracks how many products have been created, and a staticgetTotalProducts()method. Test it by creating several products.
Extension
-
Auto-incrementing ID – Create a
Ticketclass where each ticket automatically gets a unique ID (starting from 1001). Use a static counter. IncludegetTicketId()(instance) andgetNextTicketId()(static). -
Utility class – Create a
Validatorclass with only static methods:isPositive(int n),isInRange(int n, int min, int max),isNonEmpty(String s). No constructor should be needed – explain why.
Challenge
- Design analysis – Your team is building a chat application. For each of the following, decide if it should be static or instance and justify:
Message.content(the text of a message)Message.totalMessagesSent(across all users)User.usernameUser.onlineCount(how many users are currently online)ChatRoom.sendMessage(Message m)(sends to all users in the room)
Connections
- Prerequisites: Access Modifiers –
staticis often confused with access modifiers but serves a different purpose - Prerequisites: Classes and Objects – understanding instance variables before learning what static means
- Next: Object References – how references work, aliasing,
null,==vs.equals() - Related: Encapsulation – static members follow the same
private/publicrules