Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

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

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Introduction

In this tutorial, we’ll talk about a very interesting feature that Project Valhalla brings to the Java ecosystem, Value-based Classes. Value-based classes were introduced in Java 8 and have gone through major refactors and enhancements in later releases.

2. Value-based Classes

2.1. Project Valhalla

Project Valhalla is an experimental project by OpenJDK to add new features and capabilities to Java. The primary goal of this initiative is to add improved support for value types, generic specialization, and performance improvements while maintaining complete backward compatibility.

Value-based classes are one of the features introduced by Project Valhalla to introduce primitive, immutable values to the Java language without the added overhead that traditional object-oriented classes bring.

2.2. Primitives and Value-Types

Before we come to the formal definition of value-based classes, let’s look at two important semantics in Java – primitives and value types.

Primitive data types, or primitives, in Java, are simple data types that represent a single value and are not objects. Java provides eight such primitive data types: byte, short, int, long, float, double, char, and boolean. While these are simple types, Java provides wrapper classes for each of these for us to interact with them in an object-oriented way.

It is also important to remember that Java performs auto-boxing and unboxing automatically to convert between the object and primitive type efficiently:

List<Integer> list = new ArrayList<>();
list.add(1); // this is autoboxed

Primitive types live on the stack memory, while the objects that we use in our code live on the heap memory.

Project Valhalla introduced a new type in the Java ecosystem that is somewhat between an object and a primitive, and it is termed a value-type. Value types are immutable types, and they do not have any identity. These value types also do not support inheritance.

Value types are not addressed by their reference but by their values, just like primitives.

2.3. Value-Based Classes

Value-based classes are classes that are designed to behave like and encapsulate value-types in Java. The JVM can freely switch between value types and its value-based class, much like auto-boxing and unboxing. Value-based classes are hence, identity free, for the same reason.

3. Properties of Value-Based Classes

Value-based classes are classes that represent simple immutable values. A Value-based class has several properties that can be categorized into some general themes.

3.1. Immutability

Value-based classes are meant to represent immutable data, similar to primitives like int, and have the following characteristics:

  • A value-based class is always final
  • It contains only the final fields
  • The class can extend the Object class or a hierarchy of abstract classes that declare no instance fields

3.2. Object Creation

Let’s understand how creating new objects of value-based classes works:

  • The class does not declare any accessible constructor
  • In case there are accessible constructors, they should be marked as deprecated for removal
  • The class should be instantiated only through factory methods. The instance received from the factory may or may not be a new instance, and the calling code should not make any assumption about its identity

3.3. Identity and equals(), hashCode(), toString() Methods

Value-based classes are identity-free. As they are still classes in Java, we need to understand how methods inherited from Object class happens:

  • The implementations of equals(), hashCode(), and toString() are defined solely based on the values of its instance members and not from their identities, nor any other instance’s state
  • We consider two objects to be equal solely on the objects’ equals() check and not on reference-based equality, i.e. ==
  • We can use two equal objects interchangeably, and they should produce the same result on any computation or method invocation.

3.4. Some Additional Caveats

We should consider some additional limitations while working with value-based classes:

  • Two objects, which are equal based on the equals() method, might be different objects in the JVM or the same
  • We cannot ensure exclusive ownership of the monitor, making instances unsuitable for synchronization

4. Examples of Value-Based Classes

4.1. Value-Based Classes in the JDK

There are several classes in the JDK that follow the Value-based class specification.

When it was first introduced, java.util.Optional and the DateTime API (java.time.LocalDateTime) were value-based classes. As of Java 16 and beyond, Java has defined all the wrapper classes of primitive types such as Integer and Long as value-based.

These classes have the @ValueBased annotation from the jdk.internal package present:

@jdk.internal.ValueBased
public final class Integer extends Number implements Comparable<Integer>, Constable, ConstantDesc {
    // Integer class in the JDK
}

4.2. Custom Value-Based Class

Let’s create our custom class which follows the value-based class specification defined above. For our example, let’s take a Point class which identifies a point in 3D space. The class has 3 integer fields x, y, and z.

We can argue that the Point definition serves as a good candidate for a value-based class because a specific point in space is unique and can be referred to only by its value. It is constant and unambiguous, much like an integer of value 302.

We’ll start by defining the class to be final and its attributes x, y, and z as final. Let’s also make the constructor private:

public final class Point {
    private final int x;
    private final int y;
    private final int z;
    // inaccessible constructor
    private Point(int x, int y, int z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    // ...
}

Now, let’s have the origin(0, 0, 0) instance of the class created beforehand, and we return the same instance every time there is a call to create a point with x = 0, y = 0, and z = 0:

private static Point ORIGIN = new Point(0, 0, 0);

We now need to provide an object creation mechanism in the form of a factory method:

public static Point valueOfPoint(int x, int y, int z) {
    // returns a cached instance if it is the origin, or a new instance
    if (isOrigin(x, y, z)) {
        return ORIGIN;
    }
    return new Point(x, y, z);
}

// checking if a point is the origin
private static boolean isOrigin(int x, int y, int z) {
    return x == 0 && y == 0 && z == 0;
}

The factory method valueOfPoint() could return a new instance or a cached one depending on the parameters. This forces the calling code not to make any assumption on the state of the object or compare references of two instances. 

Finally, we should define the equals() method based only on the values of instance fields:

@Override
public boolean equals(Object other) {
    if (other == null || getClass() != other.getClass()) {
        return false;
    }
    Point point = (Point) other;
    return x == point.x && y == point.y && z == point.z;
}

@Override
public int hashCode() {
    return Objects.hash(x, y, z);
}

We now have a class Point, which can behave as a value-based class. We can put the @ValueBased annotation to the class after importing it from jdk.internal package. However, it is not mandatory for our case.

Let’s now test that two instances of the same point in space denoted by (1,2,3) are equal:

@Test
public void givenValueBasedPoint_whenCompared_thenReturnEquals() {
    Point p1 = Point.valueOfPoint(1,2,3);
    Point p2 = Point.valueOfPoint(1,2,3);

    Assert.assertEquals(p1, p2);
}

Additionally, for the sake of this exercise, let’s also see that two instances, if compared by reference, are the same when two origin points are created:

@Test
public void givenValueBasedPoint_whenOrigin_thenReturnCachedInstance() {
    Point p1 = Point.valueOfPoint(0, 0, 0);
    Point p2 = Point.valueOfPoint(0, 0, 0);

    // the following should not be assumed for value-based classes
    Assert.assertTrue(p1 == p2);
}

5. Advantages of Value-Based Classes

Now that we know what value-based classes are and how we can define one, let’s understand why we might need value-based classes at all.

Value-based classes being part of the Valhalla specification, are still in the experimental phase and continue to evolve. Therefore, the benefits of such classes may change over time.

As of now, the most important benefit that comes out of using value-based classes is memory utilization. Value-based classes are more memory efficient as they do not have reference-based identity. Additionally, the JVM can reuse existing instances or create new ones based on the requirements, thereby reducing the memory footprint.

Also, they do not require synchronization, increasing overall performance, especially in multithreaded applications.

6. Difference Between Value-Based Classes and Other Types

6.1. Immutable Classes

Immutable classes in Java share a lot of common ground with Value-based classes. Hence, it is very crucial to understand the differences between them.

While value-based classes are new and part of an ongoing experimental feature, Immutable classes have been a core and integral part of the Java ecosystem for a long time. The String class, Enums, and wrapper classes in Java, such as the Integer class, are examples of immutable classes.

Immutable classes are not identity-free like value-based classes. Instances of Immutable classes having the same state are distinct, and we can compare them based on reference equality. Instances of value-based classes do not have the notion of reference-based equality:

Immutable classes are free to provide accessible constructors and can have multiple attributes and complex behaviors. However, value-based classes represent simple values and do not define complex behavior with dependent attributes.

Finally, we should note that value-based classes are, by definition, immutable but not vice-versa.

6.2. Records

Java introduced the notion of Records in Java 14 as an easy way to pass around immutable data objects. Records and value-based classes fulfill different purposes even if they seem similar in behavior and semantics.

The most noticeable distinction between records and value-based classes is that records have public constructors, while value-based classes lack them.

7. Conclusion

In this article, we talked about value-based classes and the notion of value types in Java. We touched upon the important properties that value-based classes must abide by and the benefits they bring. We also discussed the differences between value-based classes and similar Java concepts, such as immutable classes and records.

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.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

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

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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

Partner – MongoDB – NPI EA (tag=MongoDB)
announcement - icon

Traditional keyword-based search methods rely on exact word matches, often leading to irrelevant results depending on the user's phrasing.

By comparison, using a vector store allows us to represent the data as vector embeddings, based on meaningful relationships. We can then compare the meaning of the user’s query to the stored content, and retrieve more relevant, context-aware results.

Explore how to build an intelligent chatbot using MongoDB Atlas, Langchain4j and Spring Boot:

>> Building an AI Chatbot in Java With Langchain4j and MongoDB Atlas

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

eBook Jackson – NPI EA – 3 (cat = Jackson)
2 Comments
Oldest
Newest
Inline Feedbacks
View all comments