Java 14 Records vs Lombok vs POJOs

Java was never known for being an expressive language. If we look back in history, handy features such as lambda expression have been there long before – in other languages such as C#, for example. Especially writing data classes such as DTOs or model classes – without the IDE auto-generate feature for constructors and getter/setters, this would have been a real pain. But autogenerated code also has its drawbacks – it needs to be maintained, and it can be changed and is not really “clean” as we always have to look for manual changes. We, as developers, love to automate things – this is where Lombok comes into play. It helps us with a lot of routine work, as mentioned above. But wait, data classes – wasn’t there a JVM language with native support for that? Of course, Kotlin comes to rescue. So there are already a lot of alternatives to writing more efficient code. But with the new release cycle of Java, a lot of new features “borrowed” from other languages such as Kotlin make their way faster to the regular Java language without the need for third-party library support. One of these upcoming features in Java 14 will be the native support for data classes. Let’s have a look – shorting a data class from > 30 LOC to 1 – without any libraries.

Let’s start coding

Let’s imagine we want to have a user data class with three attributes – ID, firstName, and lastName. The “plain” old Java way would look like this:

package io.viesure.java14.preview.model;

public class UserJavaWay {

    int userId;
    String firstName;
    String lastName;

    public UserJavaWay(int userId, String firstName, String lastName) {
        this.userId = userId;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

Nothing special. A lot of boilerplate code. Let’s introduce Lombok for comparison:

package io.viesure.java14.preview.model;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class UserLombok {
    private int userId;
    private String firstName;
    private String lastName;
}

Looks far better. We managed to shorten the class significantly, but it has some drawbacks. We need a third-party library for it, and we need to enable annotation processing: nothing evil but room for improvement. This is where Java14 records come to shine. Let’s have a look at the Java14 native solution with records:

package io.viesure.java14.preview.model;

public record UserJava14 (int userId, String firstName, String lastName) { }

And this is where the new magic comes in. Java will automatically generate everything we need to have a proper data class. Behind the scenes, the class looks like this:

package io.viesure.java14.preview.model;

public final class UserJava14 extends java.lang.Record {
    private final int userId;
    private final java.lang.String firstName;
    private final java.lang.String lastName;

    public UserJava14(int userId, java.lang.String firstName, java.lang.String lastName) { /* compiled code */ }

    public java.lang.String toString() { /* compiled code */ }

    public final int hashCode() { /* compiled code */ }

    public final boolean equals(java.lang.Object o) { /* compiled code */ }

    public int userId() { /* compiled code */ }

    public java.lang.String firstName() { /* compiled code */ }

    public java.lang.String lastName() { /* compiled code */ }
}

Besides, as expected, all getter and setter have been generated. There are also hashCode(), equals(), and a toString() method. Everything we need with just one line of Java Code. If you want to have a look at the full power of this feature you can find it here (https://openjdk.java.net/jeps/359)

Hint: If you also want to have a look at your generated classes go to your compiled class files within your target folder and use javap command e.g., javap UserJava14

The complete example code is here:

You need to install Java 14 (https://jdk.java.net/14/). If you do not want to use the command line to compile your files, IntelliJ EAP already supports most of the Java 14 Features (https://www.jetbrains.com/idea/nextversion)

Summary

Java is getting more and more handy features and syntactic sugar. Keep in mind that Records are still a preview feature and therefore are not ready for production in any way. But in general, the direction in which Java as a language is heading it getting it closer and closer to developer loved programming languages such as Kotlin (see https://www.youtube.com/watch?v=te3OU9fxC8U for which features may get from Kotlin to Java). There are a lot of new upcoming features (e.g., https://blog.jetbrains.com/idea/2020/03/java-14-and-intellij-idea/) in the next years, which will make the task of programming more straight forward and the code easier to maintain.   

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.