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
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.
