Static: What, why, and how?
samwho keyboard logo

Static: What, why, and how?

Prerequisite knowledge: Basic object orientation (especially the this keyword), basic Java. I will be compiling and running the Java from the command line, code examples that start with a dollar sign $ are lines executed from the command line from the directory that the code resides.

So you've been programming for a little while now, maybe you're programming in Java and you've been noticing this "static" word lying around. What does it mean?

Let's say we have this code:

public class Application {
  public static void main(String[] args) {
    Application.sayHello();
  }

  public static void sayHello() {
    System.out.println("Hello, world!");
  }
}

Compile and run:

$ javac Application.java
$ java Application

Output:

Hello, world!

You've seen the method signature public static void main before. It has a special meaning in Java (and lots of other languages) as the entry point of the program. The sayHello() method is new, though. Notice how we call the method by using the class name in front of it, Application.sayHello(). This is because the formal definition of a static method is:

A method that does not require access, nor can modifiy an instance of the class it belongs to.

Because the method does not require any knowledge of instances of the class, it should be called from the class itself. It is possible to call static methods from objects of the class, but it isn't good practice. This code, for example, compiles and runs fine:

public class Application {
  public static void main(String[] args) {
    Application a = new Application();
    a.sayHello();
  }

  public static void sayHello() {
    System.out.println("Hello, world!");
  }
}

Compile and run:

$ javac Application.java
$ java Application

Output:

Hello, world!

However, it isn't clear that you're calling a static method in this code, thus it is considered bad practice.

Conversely, static methods do not have access to instances of the class they belong to. For example, using the this keyword or attempting to call a non-static method from a static method will raise an error:

public class Application {
  public int greets = 0;

  public static void main(String[] args) {
    this.greet();
  }

  public void greet() {
    System.out.println("Hi there!");
    greets++;
  }
}

Compile:

$ javac Application.java

Compile error:

Application.java:5: non-static variable this cannot be referenced from a static context
  this.greet();
  ^
1 error

The main method is static and cannot refer to non-static methods of the class. The use of the this keyword in a static context doesn't make any sense because static methods aren't part of any instance of the class, they are a part of the class itself. this simply does not exist in static methods.

Static methods are often referred to as class methods and non-static methods are called instance methods. If you hear anyone talking about class methods or variables, you could substitute class for static and it would be the same thing.

# The Static Usecase

So we've had an explanation of static and we've seen a few contrived examples but what about a real example? Where are static methods used in the real world?

The most prominent example I can think of is in the Singleton design pattern. The Singleton design pattern is used to restrict the amount of objects of a class to one. With static methods, this is an easy task:

public class Application {
  private static Application singleton = null;

  public static Application getInstance() {
    if (singleton == null) {
      singleton = new Application();
    }

    return singleton;
  }

  private Application() {
    // intentionally empty, declared private
  }
}

The class contains one static variable that is a reference to an instance of itself and it has a method that creates that instance if it does not exist and then returns it. No matter how many times you call the Application.getInstance() method, it will always return the same instance of the class, and because the constructor is private you cannot create instances of the class outside of the class.

Here's an example that proves the method returns the same instance of the Application class every time:

import java.util.Random;

public class Application {
  private static Application singleton = null;

  public static Application getInstance() {
    if (singleton == null) {
      singleton = new Application();
    }

    return singleton;
  }

  public int seed = 0;

  private Application() {
    Random rand = new Random();
    this.seed = rand.nextInt();
  }

  public static void main(String[] args) {
    Application app = Application.getInstance();
    System.out.println(app.seed);

    app = Application.getInstance();
    System.out.println(app.seed);

    app = Application.getInstance();
    System.out.println(app.seed);
  }
}

The top part of the code example is the same as the previous example with a slight change to the constructor. The constructor now generates a random number and assigns the instance variable seed to that random number.

The main method then gets an instance of the Application class and prints out the contents of the seed. It does this three times to prove that the seed is the same every time. Here's the output:

1180384142
1180384142
1180384142

Your output will vary but the point is that the same number is printed out three times. This signifies that the same instance of the Application class is being returned from Application.getInstance(); each time.

# The Singleton Usecase

I've said that static methods and variables are used with the Singleton pattern, but where is the Singleton pattern used?

The most common use for the Singleton pattern that I have seen is configuration files. For example, ThinkUp uses the Singleton pattern for its Config class, which can be found here.

The Config class reads a configuration file in the code base and then stores all of the options in an array made available in a singleton object. This makes the configuration options available globally to the application and stops developers creating multiple instances of the Config class and potentially causing problems when the configuration is modified on the fly.

powered by buttondown