Static Methods
What Static Methods Are
A static method belongs to the class, not to an instance. It is called on the class name and has no implicit this reference. This means a static method cannot directly access instance (non-static) fields or call instance methods — there is no “current object” to operate on.
public class MathUtils {
public static double average(double a, double b) {
return (a + b) / 2.0;
}
}
double result = MathUtils.average(10.5, 20.3);
No MathUtils object is created. The method is called purely through the class.
The Static Context Rule
The most important rule about static methods — and a favourite Tripos trap — is:
From a static context, you can only reference other static members directly. To access instance members, you need an explicit object reference.
public class Counter {
private int value = 0; // instance field
private static int totalCount = 0; // static field
public void increment() { // instance method
this.value = this.value + 1; // OK — instance context
totalCount = totalCount + 1; // OK — static field accessible from instance
}
public static int getTotalCount() { // static method
return totalCount; // OK — static field
}
public static void reset() { // static method
value = 0; // COMPILE ERROR! Cannot access instance field
this.value = 0; // COMPILE ERROR! No 'this' in static context
increment(); // COMPILE ERROR! Cannot call instance method
}
}
The fix is to create an instance and call methods on it, or to make the method non-static:
public static void reset(Counter c) {
c.value = 0; // OK — explicit object reference provided
}
Common Uses of Static Methods
Utility Methods
Pure functions that operate only on their parameters and have no side effects are natural candidates for static methods. The JDK is full of examples:
Math.sqrt(16.0);
Math.max(3, 7);
Collections.sort(myList);
Arrays.copyOf(original, newLength);
These methods do not need object state — they are computational building blocks.
Factory Methods
A static method that creates and returns instances of a class is a factory method. This is often cleaner than overloaded constructors because the method name can describe intent:
public class LocalDate {
public static LocalDate of(int year, int month, int day) {
return new LocalDate(year, month, day);
}
public static LocalDate now() {
return new LocalDate(/* current system date */);
}
public static LocalDate parse(String text) {
return new LocalDate(/* parse from ISO format */);
}
}
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(2000, 3, 15);
LocalDate parsed = LocalDate.parse("2025-07-15");
Factory methods can also return subtypes, cache instances, or enforce invariants in ways that constructors cannot because constructors must always return a new instance of the exact class.
The main Method
public static void main(String[] args) must be static because the JVM calls it before any objects exist. There is no instance of the containing class at the moment the program starts — the JVM would have no object to call an instance method on.
Static Factories for Immutable Value Types
When a value type is immutable (like String or Integer), static factory methods can offer instance-controlled creation:
Integer.valueOf(42); // may return a cached instance
Integer.parseInt("42"); // returns a primitive, not an Integer object
Contrast with Instance Methods
| Instance Method | Static Method | |
|---|---|---|
| Called on | An object reference obj.method() | The class name Class.method() |
Has this? | Yes — refers to the receiver object | No — no receiver |
| Accesses instance fields? | Yes | No (directly) |
| Accesses static fields? | Yes | Yes |
| Can be overridden? | Yes (unless final) | No (hidden, not overridden) |
| Typical use | Behaviour that depends on an object’s state | Behaviour that is independent of any particular object |
Static Import
The import static statement lets you use static members without qualifying them with the class name:
import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
double circumference = 2 * PI * radius;
double root = sqrt(16.0);
Use sparingly — it can make code harder to read when the origin of a name is not obvious. import static org.junit.Assert.* is common in test code.
Common Tripos Traps
Static Method Overriding (Which Does Not Exist)
class Parent {
public static void greet() {
System.out.println("Hello from Parent");
}
}
class Child extends Parent {
public static void greet() {
System.out.println("Hello from Child");
}
}
Parent p = new Child();
p.greet(); // Prints "Hello from Parent" — static dispatch, not dynamic!
Static methods are resolved at compile time based on the declared type of the variable, not the runtime type of the object. The @Override annotation does not compile on static methods. This is called hiding, not overriding.
Calling Non-Static from Static
Every exam will test this in some form. If you see a static method attempting to access an instance field or call an instance method without an explicit object reference, it is a compile error.
The Implicit ‘this’ in Inner Classes
An inner (non-static nested) class has an implicit reference to the enclosing instance. Its methods can access the enclosing instance’s fields. But a static nested class has no such reference — it behaves like a top-level class and can only access static members of the enclosing class.