eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

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

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this tutorial, we’ll explore the static keyword of the Java language in detail. The static keyword means that a member – like a field or method – belongs to the class itself, rather than to any specific instance of that class. As a result, we can access static members without the need to create an instance of an object.

We’ll begin by discussing the differences between static and non-static fields and methods. Then, we’ll cover static classes and code blocks, and explain why non-static components can’t be accessed from a static context.

2. 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 instantiate a class. There will always be only one copy of static field belonging to it. The value of this static field is shared across all objects of the same class. From the memory perspective, static variables are stored in the heap memory.

Imagine a class with several instance variables, where each new object created from this class has its own copy of these variables. However, if we want a variable to track the number of objects created we use a static variable instead. This allows the counter to be incremented with each new object:

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
}

As a result, the static variable numberOfCars will be incremented each time we instantiate the Car class. Let’s create two Car objects and expect the counter to have a value of two:

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

As we can see static fields can come in handy when:

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

Lastly, it’s important to know that static fields can be accessed through an instance (e.g. ford.numberOfCars++) or directly from the class (e.g. Car.numberOfCars++). The latter is preferred, as it clearly indicates that it’s a class variable rather than an instance variable.

3. The static Methods (Or Class Methods)

Similar to static fields, static methods also belong to a class instead of an object. So, we can invoke them without instantiating the class. Generally, we use static methods to perform an operation that’s not dependent upon instance creation.

For example, we can use a static method to share code across all instances of that class:

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

Additionally, we can use static methods to create utility or helper classes. Some popular examples are the JDK’s Collections or Math utility classes, Apache’s StringUtils, and Spring Framework’s CollectionUtils.

The same as for static fields, static methods can’t be overridden. This is because static methods in Java are resolved at compile time, while method overriding is part of Runtime Polymorphism.

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.

4. The static Code Blocks

Generally, we’ll initialize static variables directly during declaration. However, if the static variables require multi-statement logic during initialization we can use a static block instead.

For instance, let’s initialize a List object with some predefined values using static block of code:

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");
    }
}

As we can see, it wouldn’t be possible to initialize a List object with all the initial values along with the declaration. So, this is why we’ve utilized the static block here.

A class can have multiple static members. The JVM will resolve the static fields and static blocks in the order of their declaration. To summarize, the main reasons for using static blocks are:

  • to initialize static variables needs some additional logic apart from the assignment
  • to initialize static variables with a custom exception handling

5. The static Inner Classes

Java allows us to create a class within a class. It provides a way of grouping elements we use in a single place. This helps to keep our code more organized and readable.

In general, the nested class architecture is divided into two types:

  • 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 ones), whereas the static nested classes only have access to static members of the outer class.

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.

For example, we can use a nested static class to implement the singleton pattern:

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.

Additionally, we can use a nested static class where visibility between parent and nested members is displayed, and vice versa:

public class Pizza {

    private static String cookedCount;
    private boolean isThinCrust;

    public static class PizzaSalesCounter {

        private static String orderedCount;
        public static String deliveredCount;

        PizzaSalesCounter() {
            System.out.println("Static field of enclosing class is "
              + Pizza.cookedCount);
            System.out.println("Non-static field of enclosing class is "
              + new Pizza().isThinCrust);
        }
    }

    Pizza() {
        System.out.println("Non private static field of static class is "
          + PizzaSalesCounter.deliveredCount);
        System.out.println("Private static field of static class is "
          + PizzaSalesCounter.orderedCount);
    }

    public static void main(String[] a) {
           new Pizza.PizzaSalesCounter();
    }
}

The result when we run the main method is:

Static field of enclosing class is null
Non private static field of static class is null
Private static field of static class is null
Non-static field of enclosing class is false

Basically, a static nested class doesn’t have access to any instance members of the enclosing outer class. It can only access them through an object’s reference. The main reasons for using static inner classes in our code are:

  • grouping classes intended for use in only one place increases encapsulation.
  • to bring the code closer to the only place that will use it. This increases readability, and the 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, we won’t couple it to the outer class, and they won’t require any heap or stack memory.

6. Understanding the “Non-static variable” Error

The error “Non-static variable cannot be referenced from a static context” occurs when a non-static variable is used inside a static context. As we saw earlier, the JVM loads static variables at class load time, and they belong to the class. On the other hand, we need to create an object to refer to non-static variables.

So, the Java compiler complains because there’s a need for an object to call or use non-static variables.

Now that we know what causes the error, let’s illustrate it using an example:

public class MyClass { 
    int instanceVariable = 0; 
    
    public static void staticMethod() { 
        System.out.println(instanceVariable); 
    } 
    
    public static void main(String[] args) {
        MyClass.staticMethod();
    }
} 

As we can see, we used instanceVariable, which is a non-static variable, inside the static method staticMethod(). Consequently, we’ll get the error Non-static variable cannot be referenced from a static context.

7. Conclusion

In this article, we saw the static keyword in action and discussed the main reasons for using static fields, methods, blocks, and inner classes.

Finally, we learned what causes the compiler to fail with the error “Non-static variable cannot be referenced from a static context”.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

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

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)