Records are not “Lombok-lite”

Recreating Lombok is not the purpose of Java record.

The purpose of Java record is to provide an explicit vehicle for transparently communicating shallowly-immutable data.

Technically, records are Java’s nominal tuple. Tuple means an ordered set of fields. Nominal means the fields have names, as does their container. Practically, you can think of a Java record as a struct on steroids.

See the official document for scope and purpose, JEP 395: Records.

So no Builder feature need be provided by default as that lies outside the scope of Java record. However, you can easily create your own Builder for any particular record class.

AI-generated

Actually, you need not write your own Builder implementation. Let a generative AI draft the code on your behalf. (Be sure to review carefully as these AIs are imperfect.)

For example:

write code for a Builder class for the Java record record Person ( String name , LocalDate birth ){}

Ecosia AI chat feature produces:

public record Person(String name, LocalDate birth) {
    
    public static class Builder {
        private String name;
        private LocalDate birth;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder birth(LocalDate birth) {
            this.birth = birth;
            return this;
        }

        public Person build() {
            return new Person(name, birth);
        }
    }
}

That code worked for me, copy-pasted, with no edits needed.

Usage:

Person person = new Person.Builder()
    .birth(LocalDate.of(2001, Month.JANUARY, 23))
    .name("Alice")
    .build();

person.toString() // ➡️ Person[name=Alice, birth=2001-01-23]

Withers

By the way, work is underway to add “withers”, a feature to instantiate a new record object based on the payload values of another. See JEP 468: Derived Record Creation (Preview).

Jakarta Validation

You may want to use Jakarta Validation (previously known as Bean Validation) to verify the validity of your new record object’s state.

Likewise, you might use Jakarta Validation in your Builder implementation.

IDE code generation

Your IDE may have a feature for generating code for a Builder from a given Java Record.

For example, IntelliJ has a built-in feature Replace Constructor with Builder. However that does not work for Java Record. But there is a plugin for that. The Record Builder Plugin can “automatically generate builder classes for your Java Records, JavaBeans and Interfaces, allowing you to select fields and configure the generated builder”.

RecordBuilder library

RecordBuilder is an interesting project that lets you mark a Java record with an annotation. Then RecordBuilder generates code for builders and withers.

I’ve not yet tried using this library, so I cannot vouch for it.

Answer from Basil Bourque on Stack Overflow
🌐
GitHub
github.com › Randgalt › record-builder
GitHub - Randgalt/record-builder: Record builder generator for Java records · GitHub
Can be used instead of new NameAndAge(...) */ public static NameAndAge NameAndAge(String name, int age) { return new NameAndAge(name, age); } /** * Return a new builder with all fields set to default Java values */ public static NameAndAgeBuilder builder() { return new NameAndAgeBuilder(); } /** * Return a new builder with all fields set to the values taken from the given record instance */ public static NameAndAgeBuilder builder(NameAndAge from) { return new NameAndAgeBuilder(from.name(), from.age()); } /** * Return a "with"er for an existing record instance */ public static NameAndAgeBuilder
Starred by 921 users
Forked by 70 users
Languages   Java
🌐
How to do in Java
howtodoinjava.com › home › java basics › builder pattern for java records
Builder Pattern for Java Records
August 6, 2024 - The builder pattern aims to provide a flexible solution for constructing complex data structures by separating the build process from the final representation of the data structure.
Discussions

Records and @Builder
It does not defeat the purpose. Records are immutable data objects. How you initialize them, is up to you and using the builder pattern on big data objects makes sense as sometimes the default record constructor might be inflexible. If you don't want to use lombok (@Builder), this works great: https://github.com/Randgalt/record-builder More on reddit.com
🌐 r/javahelp
12
2
September 2, 2024
ANN: Record Builder (early access) for Java Records

I see a builder as vital to complete Java records. The JDK will get around to it eventually (and likely other tools) but I thought I'd add it now.

Example

@RecordBuilder  
public record NameAndAge(String name, int age){}

This will generate a builder class that can be used ala:

// build from components
var n1 = NameAndAgeBuilder.builder().name(aName).age(anAge).build();

// generate a copy with a changed value
var n2 = NameAndAgeBuilder.builder(n1).age(newAge).build(); // name is the same as the name in n1

// pass to other methods to set components
var builder = new NameAndAgeBuilder();
setName(builder);
setAge(builder);
var n3 = builder.build();
More on reddit.com
🌐 r/java
37
42
December 16, 2019
Is Record feature in Java 16 an alternative to builder classes? - Stack Overflow
Records provide immutability to an object, so does builder pattern. what are pros and cons of using record in place of builder? More on stackoverflow.com
🌐 stackoverflow.com
[deleted by user]

Java is backwards compatible in that you can run an application developed and compiled with an older version of Java on a newer version. You can't however run something compiled with a newer Java on an older version.

Java 9 did change things a good bit so older applications likely need some command line arguments to run correctly.

More on reddit.com
🌐 r/javahelp
8
9
January 25, 2018
Top answer
1 of 1
23

Records are not “Lombok-lite”

Recreating Lombok is not the purpose of Java record.

The purpose of Java record is to provide an explicit vehicle for transparently communicating shallowly-immutable data.

Technically, records are Java’s nominal tuple. Tuple means an ordered set of fields. Nominal means the fields have names, as does their container. Practically, you can think of a Java record as a struct on steroids.

See the official document for scope and purpose, JEP 395: Records.

So no Builder feature need be provided by default as that lies outside the scope of Java record. However, you can easily create your own Builder for any particular record class.

AI-generated

Actually, you need not write your own Builder implementation. Let a generative AI draft the code on your behalf. (Be sure to review carefully as these AIs are imperfect.)

For example:

write code for a Builder class for the Java record record Person ( String name , LocalDate birth ){}

Ecosia AI chat feature produces:

public record Person(String name, LocalDate birth) {
    
    public static class Builder {
        private String name;
        private LocalDate birth;

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder birth(LocalDate birth) {
            this.birth = birth;
            return this;
        }

        public Person build() {
            return new Person(name, birth);
        }
    }
}

That code worked for me, copy-pasted, with no edits needed.

Usage:

Person person = new Person.Builder()
    .birth(LocalDate.of(2001, Month.JANUARY, 23))
    .name("Alice")
    .build();

person.toString() // ➡️ Person[name=Alice, birth=2001-01-23]

Withers

By the way, work is underway to add “withers”, a feature to instantiate a new record object based on the payload values of another. See JEP 468: Derived Record Creation (Preview).

Jakarta Validation

You may want to use Jakarta Validation (previously known as Bean Validation) to verify the validity of your new record object’s state.

Likewise, you might use Jakarta Validation in your Builder implementation.

IDE code generation

Your IDE may have a feature for generating code for a Builder from a given Java Record.

For example, IntelliJ has a built-in feature Replace Constructor with Builder. However that does not work for Java Record. But there is a plugin for that. The Record Builder Plugin can “automatically generate builder classes for your Java Records, JavaBeans and Interfaces, allowing you to select fields and configure the generated builder”.

RecordBuilder library

RecordBuilder is an interesting project that lets you mark a Java record with an annotation. Then RecordBuilder generates code for builders and withers.

I’ve not yet tried using this library, so I cannot vouch for it.

🌐
Baeldung
baeldung.com › home › java › a practical guide to recordbuilder in java
A Practical Guide to RecordBuilder in Java | Baeldung
November 12, 2025 - It generates fluent, immutable-friendly builders that remove the need for manual constructors or update methods. Its real strength is balance: flexible updates without losing immutability, and expressive code without boilerplate. Whether we’re building DTOs, API responses, or config objects, it fits naturally into our workflow. With almost no setup, RecordBuilder becomes a powerful tool for clean, scalable Java development.
🌐
Coderanch
coderanch.com › t › 776593 › code-reviews › engineering › Java-Record-Builder-Practice
Java Record Builder Best Practice (Code Reviews forum at Coderanch)
September 16, 2023 - Validating the input parameters is covered by using a "custom constructor" in the record declaration. In your code it would look something like this: So that should take care of the validation part. That leaves the Builder to provide the fluid interface, which looks like it can't be made compulsory but maybe that isn't as much of a problem.
🌐
DEV Community
dev.to › agavrilov76 › record-companion-simple-builder-pattern-for-java-records-4h9f
Record Companion: Simple Builder Pattern for Java Records - DEV Community
September 21, 2025 - Record Companion focuses on simplicity and ease of use, making it perfect if you just want straightforward builder patterns without the extra bells and whistles. Java Records gave us immutable data structures. ValidCheck gave us clean validation.
🌐
Oracle
docs.oracle.com › en-us › iaas › tools › java › latest › com › oracle › bmc › datalabelingservicedataplane › model › Record.Builder.html
Record.Builder (Oracle Cloud Infrastructure Java SDK - 3.90.0)
java.lang.Object · com.oracle.bmc.datalabelingservicedataplane.model.Record.Builder · Enclosing class: Record · public static class Record.Builder extends Object · clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait ·
🌐
JetBrains
plugins.jetbrains.com › plugin › 24331-record-builder
Record Builder Plugin for IntelliJ IDEA & Android Studio
The Record Builder Plugin for IntelliJ offers an effortless way to use the Builder Pattern in your Java code. This plugin allows you to automatically generate builder...
Find elsewhere
🌐
Medium
medium.com › @pravin3c › 3-ways-to-create-builder-pattern-for-java-records-441cb3bc94b3
3 Ways to Create Builder Pattern for Java Records | by Pravin Choudhary | Medium
April 5, 2024 - It allows step-by-step construction of complex objects and can be particularly useful when you have several optional parameters. Java record types being immutable, by default, the builder pattern is an excellent match for records.
🌐
Medium
medium.com › @sskmal › java-records-6736f45a6aa7
Java Records and Builder pattern For Record | by sunimal malkakulage | Medium
August 21, 2024 - Validation: You can add validation logic in the build() method or within individual setter methods in the builder, ensuring that only valid objects are constructed. While records are meant to be simple and straightforward, adding a builder class can make them more versatile, especially in more complex object construction scenarios.
🌐
Medium
medium.com › @trivajay259 › builder-pattern-for-java-records-f62d884e9973
Builder Pattern for Java Records. The builder pattern aims to provide a… | by Ajay Kumar | Medium
March 12, 2026 - public record Team(String name, String description, String uuid, String photoPath) { public static final class Builder{ String name; String description; String uuid; String photoPath; public Builder uuid(String uuid) { this.uuid = uuid; return this; } public Builder description(String description) { this.description = description; return this; } public Builder name(String name) { this.name = name; return this; } public Builder status(String description) { this.description = description; return this; } public Team build() { return new Team(uuid, name, name, photoPath); } } }
🌐
Sonar
sonarsource.com › blog › builders-withers-and-records-java-s-path-to-immutability
Builders, Withers, and Records - Java’s path to immutability | Sonar
February 21, 2024 - In order to achieve immutability we have different options like Builders, Withers, or the use of Record type, but ultimately, the choice between Builders and Withers depends on the specific requirements of your application and the design principles you want to follow. Builders are often preferred for complex object creation with many optional parameters, while withers can be more suitable for modifying existing immutable objects. If you are on Java 16 or above consider that the use of Records is recommended over ordinary classes as they are immutable per definition.
🌐
javaspring
javaspring.net › blog › java-records-builder
Java Records Builder: A Comprehensive Guide — javaspring.net
Instead of using a large constructor with many parameters, you use a builder class to set each parameter one by one and then build the final object. A Java Records Builder is a way to apply the builder pattern to records.
🌐
Baeldung
baeldung.com › home › java › core java › java record keyword
Java Record Keyword | Baeldung
November 5, 2025 - Records are immutable data classes that require only the type and name of fields. The equals, hashCode, and toString methods, as well as the private, final fields and public constructor, are generated by the Java compiler.
🌐
Java Code Geeks
javacodegeeks.com › home › core java
Java RecordBuilder Example - Java Code Geeks
August 13, 2025 - Automatically generate a type-safe, fluent builder for a given record. Set default values for optional fields without cluttering the constructor. Leverage compile-time type checks to avoid runtime errors.
🌐
Medium
medium.com › @alexey1.gavrilov › record-companion-simple-builder-pattern-for-java-records-f86d62f38212
Record Companion: Simple Builder Pattern for Java Records | by Alexey Gavrilov | Medium
September 21, 2025 - Record Companion: Simple Builder Pattern for Java Records Building on the foundation of clean record validation Java Records transformed how we handle immutable data in Java, but they left us with …
🌐
Reddit
reddit.com › r/java › ann: record builder (early access) for java records
r/java on Reddit: ANN: Record Builder (early access) for Java Records
December 16, 2019 - That C# API looks so nice. I wish we had that in Java. ... That's true, the copy/with operator is very nice for working with immutable records. ... I see a builder as vital to complete Java records.
🌐
Baeldung
baeldung.com › home › java › core java › custom constructor in java records
Custom Constructor in Java Records | Baeldung
January 15, 2026 - Learn how to create custom constructors for Java Records and the benefits they provide.
Top answer
1 of 2
18

Is Record feature in Java 16 is an alternative to builder classes?

Basically ... no it isn't.

Records provide immutability to an object, so does builder pattern.

That's not correct. The builder pattern can be applied to both immutable and mutable objects. It is actually about how objects are created rather than the nature of the objects themselves.

What are pros and cons of using record in place of builder?

Well, simply put, you can't use records as a replacement for the builder pattern ... because they do different (in fact, orthogonal) things. Here's a point by point comparison of conventional Java classes implemented with the builder pattern versus record types:

  • Mutability:
    • class + builder - either mutable or immutable objects can be created
    • record - immutable only
  • Validation:
    • class + builder - yes ... the builder can validate the arguments incrementally or in the build() method.
    • record - yes ... in constructors
  • Supports optional parameters:
    • class + builder - yes
    • record - no ... though you can implement overloaded constructors
  • Supports extends:
    • class + builder - yes
    • record - no ... though you can use default methods from an inherited interface.
  • Supports internal state / abstraction:
    • class + builder - yes
    • record - no
  • Less boilerplate code:
    • class + builder - yes (relative to classes implemented without a builder) and no (relative to records).
    • record - yes

The "less boilerplate" issue is nuanced. On the one hand a builder avoids the need for overloaded constructors or new calls with huge numbers of parameters. (But you need to implement the builder itself ... which is mostly boilerplate.) On the other hand a record can be implemented without any explicit methods and a simple record constructor with no body.

2 of 2
-1

The JDK Enhancement Proposal describes records as “classes that act as transparent carriers for immutable data”.

Use cases:

Reduces Boilerplate code: Historically, creating immutable objects in Java was rather painful work, records takes care of almost all of that work for us. Records also allows the class to be better focused on the business problem at hand by reducing boilerplate code. This makes it a compelling feature for implementing things like DDD-style Value Objects and Domain Events.

public record Address(String street, String postCode, String town, String country) {
}

Temporary containers of data: Records can be defined not only as stand-alone classes, but also locally inside a method. This makes them useful as temporary containers during data processing, for quickly creating ephemeral mock data in tests, etc. We will see an example of this below.

Data Validation: Records provide support for different validation. it reduces responsibilities from the developer to write such validation

@NonNull -> a field can not be null.      
@Min() -> a min value that a field can hold.  
@Max() -> a max value that a field can hold.
@GreaterThanZero -> a field can not have value less than or equal to zero.

Comparison to Builder Classes: The only advantage that a record class offers over builder classes is data validation.