Java Top

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we'll explore the static keyword of the Java language in detail.

We'll find out how we can apply the static keyword to variables, methods, blocks and nested classes, and what difference it makes.

2. The Anatomy of the static Keyword

In the Java programming language, the keyword static means that the particular member belongs to a type itself, rather than to an instance of that type.

This means we'll create only one instance of that static member that is shared across all instances of the class.

We can apply the keyword to variables, methods, blocks and nested classes.

3. The static Fields (or Class Variables)

In Java, when we declare a field static, exactly a single copy of that field is created and shared among all instances of that class.

It doesn't matter how many times we initialize a class. There will always be only one copy of static field belonging to it. The value of this static field will be shared across all objects of either the same or any different class.

From the memory perspective, static variables are stored in the heap memory.

3.1. Example of the static Field

Let's say we have a Car class with several attributes (instance variables).

Whenever we initialize new objects from this Car blueprint, each new object will have its distinct copy of these instance variables.

However, suppose we want a variable that holds the count of the number of initialized Car objects and is shared across all instances so they can access it and increment it upon their initialization.

That's where static variables come in:

public class Car {
    private String name;
    private String engine;
    
    public static int numberOfCars;
    
    public Car(String name, String engine) {
        this.name = name;
        this.engine = engine;
        numberOfCars++;
    }

    // getters and setters
}

Now for every object of this class that we initialize, the same copy of the numberOfCars variable is incremented.

So, for this case, these will be true:

@Test
public void whenNumberOfCarObjectsInitialized_thenStaticCounterIncreases() {
    new Car("Jaguar", "V8");
    new Car("Bugatti", "W16");
 
    assertEquals(2, Car.numberOfCars);
}

3.2. Compelling Reasons to Use static Fields

  • When the value of the variable is independent of objects
  • When the value is supposed to be shared across all objects

3.3. Key Points to Remember

  • Since static variables belong to a class, we can access them directly using class name. So, we don't need any object reference.
  • We can only declare static variables at the class level.
  • We can access static fields without object initialization.
  • Finally, we can access static fields using an object reference (such as ford.numberOfCars++). But we should avoid this because it becomes difficult to figure out if it’s an instance variable or a class variable. Instead, we should always refer to static variables using class name (Car.numberOfCars++).

4. The static Methods (Or Class Methods)

Similar to static fields, static methods also belong to a class instead of the object. So, we can call them without creating the object of the class in which they reside.

4.1. Example of static Method

We generally use static methods to perform an operation that is not dependent upon instance creation.

In order to share a code across all instances of that class, we write that code in a static method:

public static void setNumberOfCars(int numberOfCars) {
    Car.numberOfCars = numberOfCars;
}

We also commonly use static methods to create utility or helper classes so that we can get them without creating a new object of these classes.

Just take a look at Collections or Math utility classes from JDK, StringUtils from Apache or CollectionUtils from Spring framework and notice that all methods are static.

4.2. Compelling Reasons to Use static Methods

  • To access/manipulate static variables and other static methods that don't depend upon objects
  • static methods are widely used in utility and helper classes.

4.3. Key Points to Remember

  • static methods in Java are resolved at compile time. Since method overriding is part of Runtime Polymorphism, static methods can't be overridden.
  • Abstract methods can't be static.
  • static methods can't use this or super keywords.
  • The following combinations of the instance, class methods and variables are valid:
    1. Instance methods can directly access both instance methods and instance variables.
    2. Instance methods can also access static variables and static methods directly.
    3. static methods can access all static variables and other static methods.
    4. static methods can't access instance variables and instance methods directly. They need some object reference to do so.

5. A static Block

We use a static block to initialize static variables. Although we can initialize static variables directly during declaration, there are situations when we need to do the multiline processing.

In such cases, static blocks come in handy.

If static variables require additional, multi-statement logic during initialization, we can use a static block.

5.1. The static Block Example

Suppose we want to initialize a list object with some predefined values.

This becomes easy with static blocks:

public class StaticBlockDemo {
    public static List<String> ranks = new LinkedList<>();

    static {
        ranks.add("Lieutenant");
        ranks.add("Captain");
        ranks.add("Major");
    }
    
    static {
        ranks.add("Colonel");
        ranks.add("General");
    }
}

It wouldn't be possible to initialize a List object with all the initial values along with declaration. That's why we've utilized the static block here.

5.2. Compelling Reasons to Use static Blocks

  • If the initialization of static variables needs some additional logic except the assignment
  • If the initialization of static variables is error-prone and needs exception handling

5.3. Key Points to Remember

  • A class can have multiple static blocks.
  • static fields and static blocks are resolved and run in the same order as they are present in the class.

6. A static Class

Java programming language allows us to create a class within a class. It provides a compelling way of grouping elements that we'll only use in one place. This helps to keep our code more organized and readable.

The nested class architecture is divided into two:

  • Nested classes that we declare static are called static nested classes.
  • Nested classes that are non-static are called inner classes.

The main difference between these two is that the inner classes have access to all members of the enclosing class (including private), whereas the static nested classes only have access to static members of the outer class.

In fact, static nested classes behave exactly like any other top-level class but are enclosed in the only class that will access it, to provide better packaging convenience.

6.1. Example of static Class

The most widely used approach to create singleton objects is through a static nested class:

public class Singleton {
private Singleton() {}

private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.instance;
}
}

We use this method because it doesn't require any synchronization and is easy to learn and implement.

6.2. Compelling Reasons to Use a static Inner Class

  • Grouping classes that will be used only in one place increases encapsulation.
  • We bring the code closer to the only place that will use it. This increases readability, and code is more maintainable.
  • If a nested class doesn't require any access to its enclosing class instance members, it's better to declare it as static. This way, it won't be coupled to the outer class and is therefore more optimal, as they won't require any heap or stack memory.

6.3. Key Points to Remember

  • static nested classes do not have access to any instance members of the enclosing outer class. It can only access them through an object's reference.
  • static nested classes can access all static members of the enclosing class, including private ones.
  • Java programming specification doesn't allow us to declare the top-level class as static. Only classes within the classes (nested classes) can be made as static.

7. Conclusion

In this article, we saw the static keyword in action.

We also read about the reasons and advantages for using static fields, static methods, static blocks and static inner classes.

As always, we can find the complete code over on GitHub.

Java bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE
Generic footer banner
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Comments are closed on this article!