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.

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

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

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

1. Overview

The Java enum type provides a language-supported way to create and use constant values. By defining a finite set of values, the enum is more type safe than constant literal variables like String or int.

However, enum values are required to be valid identifiers, and we’re encouraged to use SCREAMING_SNAKE_CASE by convention.

Given those limitations, the enum value alone is not suitable for human-readable strings or non-string values.

In this tutorial, we’ll use the enum features as a Java class to attach the values we want.

Further reading:

A Guide to Java Enums

A quick and practical guide to the use of the Java Enum implementation, what it is, what problems it solves and how it can be used to implement commonly used design patterns.

Iterating Over Enum Values in Java

Learn three simple ways to iterate over a Java enum.

A Guide to Constructors in Java

Learn the basics about constructors in Java as well as some advanced tips

2. Using Java Enum as a Class

We often create an enum as a simple list of values. For example, here are the first two rows of the periodic table as a simple enum:

public enum Element {
    H, HE, LI, BE, B, C, N, O, F, NE
}

Using the syntax above, we’ve created ten static, final instances of the enum named Element. While this is very efficient, we have only captured the element symbols. And while the uppercase form is appropriate for Java constants, it’s not how we normally write the symbols.

Furthermore, we’re also missing other properties of the periodic table elements, like the name and atomic weight.

Although the enum type has special behavior in Java, we can add constructors, fields and methods as we do with other classes. Because of this, we can enhance our enum to include the values we need.

3. Adding a Constructor and a Final Field

Let’s start by adding the element names.

We’ll set the names into a final variable using a constructor:

public enum Element {
    H("Hydrogen"),
    HE("Helium"),
    // ...
    NE("Neon");

    public final String label;

    private Element(String label) {
        this.label = label;
    }
}

First of all, we notice the special syntax in the declaration list. This is how a constructor is invoked for enum types. Although it’s illegal to use the new operator for an enum, we can pass constructor arguments in the declaration list.

We then declare an instance variable label. There are a few things to note about that.

First, we chose the label identifier instead of the name. Although the member field name is available to use, let’s choose label to avoid confusion with the predefined Enum.name() method.

Second, our label field is final. While fields of an enum do not have to be final, in most cases we don’t want our labels to change. In the spirit of enum values being constant, this makes sense.

Finally, the label field is public, so we can access the label directly:

System.out.println(BE.label);

On the other hand, the field can be private, accessed with a getLabel() method. For the purpose of brevity, this article will continue to use the public field style.

4. Locating Java Enum Values

Java provides a valueOf(String) method for all enum types. Thus, we can always get an enum value based on the declared name:

assertSame(Element.LI, Element.valueOf("LI"));

However, we may want to look up an enum value by our label field as well. To do that, we can add a static method:

public static Element valueOfLabel(String label) {
    for (Element e : values()) {
        if (java.util.Objects.equals(e.label, label)) {
            return e;
        }
    }
    return Element.UNKNOWN;
}

The static valueOfLabel() method iterates the Element values until it finds a match. Note that we use java.util.Objects.equals(Object a, Object b) for a null-safe comparison, which correctly handles cases where the lookup argument or the enum’s label might be null.

If no match is found, we return a dedicated Element.UNKNOWN enum constant. This is often preferred over returning null as it forces the calling code to handle the unknown case explicitly, thus avoiding potential NullPointerExceptions.

Let’s see a quick example using our valueOfLabel() method:

assertSame(Element.LI, Element.valueOfLabel("Lithium"));
assertSame(Element.UNKNOWN, Element.valueOfLabel("Unobtainium"));

5. Caching the Lookup Values

We can avoid iterating the enum values by using a Map to cache the labels.

Note that for very small enums, typically with fewer than five members, the overhead of map creation and memory usage often outweighs the minor performance gain from avoiding a loop. Caching is most beneficial for larger enums.

To do this, we define a static final Map and populate it when the class loads:

public enum Element {

    // ... enum values

    private static final Map<String, Element> BY_LABEL = new HashMap<>();
    
    static {
        for (Element e: values()) {
            BY_LABEL.put(e.label, e);
        }
    }

   // ... fields, constructor, methods

    public static Element valueOfLabel(String label) {
        return BY_LABEL.get(label);
    }
}

As a result of being cached, it iterates the enum values only once, and it simplifies the valueOfLabel() method.

Alternatively, we can lazily construct the cache when it is first accessed in the valueOfLabel() method. In that case, we should synchronize map access to prevent concurrency problems. For example, a thread-safe lazy implementation might look like:

private static volatile Map<String, Element> BY_LABEL;

public static Element valueOfLabel(String label) {
    if (BY_LABEL == null) {
        synchronized (Element.class) {
            if (BY_LABEL == null) {
                Map<String, Element> map = new HashMap<>();
                for (Element e : values()) {
                    map.put(e.label, e);
                }
                BY_LABEL = map;
            }
        }
    }
    Element result = BY_LABEL.get(label);
    return result != null ? result : Element.UNKNOWN;
}

However, for enums, the eager population using the static block is generally the simpler and safer approach because all constants are guaranteed to be initialized before the static block runs.

6. Attaching Multiple Values

The Enum constructor can accept multiple values.

To illustrate, let’s add the atomic number as an int and the atomic weight as a float:

public enum Element {
    H("Hydrogen", 1, 1.008f),
    HE("Helium", 2, 4.0026f),
    // ...
    NE("Neon", 10, 20.180f);

    private static final Map<String, Element> BY_LABEL = new HashMap<>();
    private static final Map<Integer, Element> BY_ATOMIC_NUMBER = new HashMap<>();
    private static final Map<Float, Element> BY_ATOMIC_WEIGHT = new HashMap<>();
    
    static {
        for (Element e : values()) {
            BY_LABEL.put(e.label, e);
            BY_ATOMIC_NUMBER.put(e.atomicNumber, e);
            BY_ATOMIC_WEIGHT.put(e.atomicWeight, e);
        }
    }

    public final String label;
    public final int atomicNumber;
    public final float atomicWeight;

    private Element(String label, int atomicNumber, float atomicWeight) {
        this.label = label;
        this.atomicNumber = atomicNumber;
        this.atomicWeight = atomicWeight;
    }

    public static Element valueOfLabel(String label) {
        return BY_LABEL.get(label);
    }

    public static Element valueOfAtomicNumber(int number) {
        return BY_ATOMIC_NUMBER.get(number);
    }

    public static Element valueOfAtomicWeight(float weight) {
        return BY_ATOMIC_WEIGHT.get(weight);
    }
}

Similarly, we can add any values we want to the enum, such as the proper case symbols, “He”, “Li” and “Be”, for example.

Moreover, we can add computed values to our enum by adding methods to perform operations.

7. Controlling the Interface

As a result of adding fields and methods to our enum, we’ve changed its public interface. Therefore our code, which uses the core Enum name() and valueOf() methods, will be unaware of our new fields.

The static valueOf() method is already defined for us by the Java language, so we can’t provide our own valueOf() implementation.

Similarly, because the Enum.name() method is final, we can’t override it either.

As a result, there’s no practical way to utilize our extra fields using the standard Enum API. Instead, let’s look at some different ways to expose our fields.

7.1. Overriding toString()

Overriding toString() may be an alternative to overriding name():

@Override 
public String toString() { 
    return this.label; 
}

By default, Enum.toString() returns the same value as Enum.name().

7.2. Implementing an Interface

The enum type in Java can implement interfaces. While this approach is not as generic as the Enum API, interfaces do help us generalize.

Let’s consider this interface:

public interface Labeled {
    String label();
}

For consistency with the Enum.name() method, our label() method does not have a get prefix.

And because the valueOfLabel() method is static, we do not include it in our interface.

Finally, we can implement the interface in our enum:

public enum Element implements Labeled {

    // ...

    @Override
    public String label() {
        return label;
    }

    // ...
}

One benefit of this approach is that the Labeled interface can be applied to any class, not just enum types. Instead of relying on the generic Enum API, we now have a more context-specific API.

8. Conclusion

In this article, we’ve explored many features of the Java Enum implementation. By adding constructors, fields and methods, we see that the enum can do a lot more than literal constants.

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)