Chapter 5 - Java for Beginners Course

Static Class Members

In all the previous examples we’ve defined fields and methods that belong to the instances of the class. For example, in our Game class, we know that when we create multiple instances of it, like:

Game game1 = new Game();
Game game2 = new Game();

game1.setTitle("Basketball");
game2.setTitle("Football");

the title field of game1 is independent from the title of game2.

However, there will be cases where we’d want a field or method to belong to a class and not to its instances. For example, in cases where we want all instances to share the same field/value.

The static keyword allows us to do exactly that, it tells Java we want a given field/method to belong to the class.

To help explain this concept, let’s assume we have the following simplified version of our original Game class:

public class Game {
    private String title;

    public Game(String title) {
        this.title = title;
    }

    public void printGame() {
        System.out.println("The game is called: " + title);
    }
}

Now, as part of the system we’re building we are asked to keep track of the maximum game title length that has been created and a way of printing this value out. This value doesn’t belong to an instance of the class, and one way of modelling this is to define a static field called maxGameTitleLength such that all instances share it.

To define our new field we define it as a regular field but add the static keyword to it:

public class Game {

    private static int maxGameTitleLength;

    //...
}

Now, for the second part, to allow the system to print this value we can also define a static method, like so:

public static void printMaximumGameTitleLength() {
    System.out.println("The longest title length is: " + maxGameTitleLength);
}

With these 2 in place, our static field and method, we have a place to keep track of that maximum game title length and a way of printing it. However, we aren’t yet updating our field to actually keep track of the maximum length. We can change our constructor to do this for us:

public Game(String title) {
    this.title = title;

    if (title.length() > maxGameTitleLength) {
        maxGameTitleLength = title.length();
    }
}
The String class provides a method length() that returns the length of the string of characters it holds.

There are two things worth noting here:

  • The Constructor of a class isn’t static, so it can access the non-static fields of the class (like this.title).

  • Constructors and non-static methods can have access to static fields and methods defined in the class. Just keep in mind that the static fields are actually shared across all instances of the class.

Having said that though, static methods can’t access non-static fields. For example, if we modified our printMaximumGameTitleLength() method and added this line:

public static void printMaximumGameTitleLength() {
    System.out.println("The longest title length is: " + maxGameTitleLength);
    this.title = "";
}

The Java compiler will give us an error indicating that we can’t access the non-static title field from a static method.

Accessing static members

If we want to access a static field or invoke a static method we also use the dot (.) operator as we do with non-static fields. The main difference is that we don’t need an object reference, we can use the name of the class that owns them.

In our example above we could use Game.maxGameTitleLength to get access to the field (in this case the static field is private though, so only the Game class itself can access it).

In the same way, to invoke our static method, we can use the name of the class directly without the need of an object reference, as in: Game.printMaximumGameTitleLength().

Accessing static members using object references

Even though we can access static fields and methods using the name of the class, Java also allows us to access them via an object reference. For example, this code is valid:

Game hockey = new Game("hockey");
hockey.printMaximumGameTitleLength();

However, this approach isn’t recommended as it doesn’t make it clear that the method is static and belongs to the class. The recommended approach is the one mentioned before, for example:

Game.printMaximumGameTitleLength();

Running our example code

Now, let’s give the above a try. Our final Game class should look like this:

public class Game {

    private static int maxGameTitleLength;

    private String title;

    public Game(String title) {
        this.title = title;

        if (title.length() > maxGameTitleLength) {
            maxGameTitleLength = title.length();
        }
    }

    public void printGame() {
        System.out.println("The game is called: " + title);
    }

    public static void printMaximumGameTitleLength() {
        System.out.println("The longest title length is: " + maxGameTitleLength);
    }

}

And let’s create a couple of instances to try this out:

In the example code run the JavaStaticMembersApp
Game game1 = new Game("chess");

// so far we've only created one instance and the max length so far is 5 ("chess")
Game.printMaximumGameTitleLength();

Game game2 = new Game("football");

// "football" has 8 characters, so we expect our maximum to be 8 now
Game.printMaximumGameTitleLength();

Game game3 = new Game("go");

// maximum is still 8
Game.printMaximumGameTitleLength();

Output:

The longest title length is: 5
The longest title length is: 8
The longest title length is: 8

Static methods and inheritance

The rules we saw about method overriding in inheritance don’t apply to static methods. When a static method of a subclass has the same signature as a static method in its superclass the effect we get is method hiding.

Even further, if a static method in the subclass has the same signature as a non-static one in the superclass or viceversa, the Java compiler will give us an error indicating this isn’t valid.

Code in GitHub

Get the code for this tutorial using the links below.

Project Repo
Download code for this step
Main class for this step
Dependencies

This is a list of recommended tutorials or courses that might be useful before starting this one.

Contents
Welcome to the Course!
Course Introduction
Chapter 1 - Building Blocks
Quick introduction to Java Variables Classes And Objects Class Example - Defining a class Object Examples - Creating instances Java Application Example - Running our first app Accessing class members - The dot operator Packages - Organizing the code
Chapter 2 - Primitives and Operators
Primitives Arithmetic Operators Assignment Operator Unary Operators Equality and Relational Operators Conditional Operators
Chapter 3 - Statements and Control Flow
Expressions Statements If-Then Statement If-Then-Else Statement More If Statements Switch Statement While and Do-While Statements For Statement Branching Statements Exception Handling
Chapter 4 - Code Example
Example Project - A Simple Vending Machine Adding money Delivering Items Giving Change
Chapter 5 - Classes and Interfaces
Introduction Access Level Modifiers Class Declaration - Class, Methods and Fields Class Declaration - Constructors Inheritance Basics Inheritance - Constructors Inheritance - Methods and Fields Polymorphism Abstract Classes and Methods Interfaces Static Class Members Class Composition Final Classes and Class Members Generic Classes
Chapter 6 - Base Object Behaviors
Introduction Type Comparison Type Casting Object Equality - The Contract Object Equality - Common Pitfalls Object String Representation Garbage Collection Object Comparison Primitive Wrappers and Autoboxing
Chapter 7 - Data Structures
Introduction Arrays - Declaration and Creation Arrays - Basic Operations Core Collection Interfaces List and ArrayList - Basic Operations ArrayList Internals Introduction to Hash Tables Map and HashMap - Basic Operations Set and HashSet - Basic Operations
Chapter 8 - Anonymous classes and lambdas
Introduction Filtering a List Anonymous Classes Lambdas Built-in Functional Interfaces
Chapter 9 - Streams
Introduction Creating Streams Intermediate Operations Terminal Operations