DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Migrating From Lombok to Records in Java
  • Simplifying Data Entities in Spring Data With Java Records
  • Java 21 Record and Pattern Matching: Master Data-Oriented Programming[Video]
  • Introduction to Apache Kafka With Spring

Trending

  • Vibe Coding With GitHub Copilot: Optimizing API Performance in Fintech Microservices
  • Is Agile Right for Every Project? When To Use It and When To Avoid It
  • Start Coding With Google Cloud Workstations
  • Automating Data Pipelines: Generating PySpark and SQL Jobs With LLMs in Cloudera
  1. DZone
  2. Coding
  3. Java
  4. Introducing Java Record

Introducing Java Record

Learn more about the latest JEP — Java Records!

By 
Peter Verhas user avatar
Peter Verhas
DZone Core CORE ·
Oct. 18, 19 · Presentation
Likes (5)
Comment
Save
Tweet
Share
30.0K Views

Join the DZone community and get the full member experience.

Join For Free

A Java record

Introducing... Java Record!

The latest JEP 359 outlines a new Java feature that may/will be implemented in some future versions of Java. The JEP suggests having a new type of "class": record.

The sample in the JEP reads as follows:

record Range(int lo, int hi) {
  public Range {
    if (lo > hi)  /* referring here to the implicit constructor parameters */
      throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
  }
}


Essentially, a record will be a class that intends to have only final fields that are set in the constructor. The JEP, as of today, also allows any other members that a class has, but essentially, a record is a record, pure data, and perhaps no functionality, at its core.

The description of a record is short and to the point and eliminates a lot of boilerplate that we would need to encode, such a class in Java 13 or less, or whichever version record will be implemented. The above code using conventional Java will look like the following:

public class Range {

    final int lo;
    final int hi;

    public Range(int lo, int hi) {
        if (lo > hi)  /* referring here to the implicit constructor parameters */
            throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
        this.lo = lo;
        this.hi = hi;
    }
}


Considering my Java::Geci code generation project, this was something that was screaming for a code generator to bridge the gap between today and the day when the new feature will be available on all production platforms.

Thus, I started to think about how to develop this generator and I faced a few issues. The Java::Geci framework can only convert a compilable project to another compilable project. It cannot work like some other code generators that convert an incomplete source code, which cannot be compiled without the modifications of the code generator, to a complete version. This is because Java::Geci works during the test phase. To get to the test phase, the code has to compile first. This is a well-known trade-off and was a design decision.

In most of the cases, when Java::Geci is useful, this is something easy to cope with. On the other hand, we gain the advantage that the generators do not need configuration management like reading and interpreting property or XML files. They only provide an API, and the code invoking them from a test configures the generators through it.

The biggest advantage is that you can even provide call-backs in forms of method references, lambdas, or object instances that are invoked by the generators so that these generators can have a totally open structure in some aspects of their working.

Why is this important in this case? The record generation is fairly simple and does not need any complex configuration. As a matter of fact, it does not need any configuration at all. On the other hand, the compilable -> compilable restrictions are affecting it. If you start to create a record using, say Java 8 and Java::Geci, then your manual code will look something like this:

@Geci("record")
public class Range {

    final int lo;
    final int hi;
}


This does not compile, because by the time of the first compilation before the code generation starts, the default constructor does not initialize the fields. Therefore, the fields cannot be final:

@Geci("record")
public class Range {

    int lo;
    int hi;
}


Running the generator, we will get:


package javax0.geci.tests.record;

import javax0.geci.annotations.Geci;

@Geci("record")
public final class Range {
    final  int  lo;
    final  int  hi;

    //<editor-fold id="record">
    public Range(final int lo, final int hi) {
        this.lo = lo;
        this.hi = hi;
    }

    public int getLo() {
        return lo;
    }

    public int getHi() {
        return hi;
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(lo, hi);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Range that = (Range) o;
        return java.util.Objects.equals(that.lo, lo) && java.util.Objects.equals(that.hi, hi);
    }
    //</editor-fold>
}


What this generator actually does is:

  • It generates the constructor
  • It converts the class and the fields to final as it is a requirement by the JEP
  • It generates the getters for the fields
  • It generates the equals() and hashCode() methods for the class

If the class has a void method that has the same (though case insensitive) name as the class, for example:


    public void Range(double hi, long lo) {
        if (lo > hi)  /* referring here to the implicit constructor parameters */
            throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
    }


Then, the generator will:

  • Invoke that method from the generated constructor
  • Modify the argument list of the method to match the current list of fields.
    public void Range(final int lo, final int hi) {
        if (lo > hi)  /* referring here to the implicit constructor parameters */
            throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
    }

    //<editor-fold id="record">
    public Range(final int lo, final int hi) {
        Range(lo, hi);
        this.lo = lo;
        this.hi = hi;
    }


Note that this generation approach tries to behave the possible closest to the actual record as proposed in the JEP and generates code that can be converted to the new syntax as soon as it is available. This is the reason why the validator method has to have the same name as the class.

When converting to a real record all that has to be done is to remove the void keyword converting the method to be a constructor, remove the argument list as it will be implicit as defined in the JEP and remove all the generated code between the editor folds (also automatically generated when the generator was executed first).

The modification of the manually entered code is a new feature of Java::Geci that was triggered by the need of the Record generator and was developed to overcome the shortcomings of the compilable -&gt; compilable restriction. How a generator can use this feature that will be available in the next 1.3.0 release of Java::Geci will be detailed in a subsequent article.

Takeaway

The takeaway of this article is that you can use Java records with Java 8, 9, ... even before it becomes available.

Record (computer science) Java (programming language)

Published at DZone with permission of Peter Verhas, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Migrating From Lombok to Records in Java
  • Simplifying Data Entities in Spring Data With Java Records
  • Java 21 Record and Pattern Matching: Master Data-Oriented Programming[Video]
  • Introduction to Apache Kafka With Spring

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!