A First Look at Records in Java 14
Here's a first look at records in Java 14.
Join the DZone community and get the full member experience.Join For Free
The upcoming release of Java will be version 14 scheduled to be in general availability in March 2020. Similar to the already released versions under the new 6-month release cycle, JDK 14 is expected to have several new features at both the language and JVM levels.
If we look at the feature list, however, we notice quite a few language features that are highly anticipated by developers: records, switch expressions (which exist in JDK 13 but in preview mode), and pattern matching. Let’s have a look at records that seems to be an interesting addition to the language.
You may also like: Introducing Java Record
All that we’re going to need is the JDK 14 Early-Access binary from the OpenJDK website: https://jdk.java.net/14/.
What Is a Record?
A record is basically a “data class,” a special kind of class that is intended to hold pure data in it. The semantics of records already exist in similar constructs in other languages such as data classes in Kotlin. By declaring a type as a record, the developer is clearly expressing their intention that the type represents only data. The syntax for declaring a record is much simpler and concise, compared to using a normal class where you typically need to implement core
Object methods like
hashCode() (often referred to as “boilerplate” code). Records seem to be an interesting choice when modeling things like domain model classes (potentially to be persisted via ORM), or data transfer objects (DTOs).
A good way to think of how records are implemented in the language is to remember enums. An enum is also a class that has special semantics with a nicer syntax. Since both are still classes, many of the features available in classes are preserved, so there is a balance between simplicity and flexibility in their design.
Records are a preview language feature, which means that, although it is fully implemented, it is not yet standardized in the JDK and can only be used by activating a flag. Preview language features can be updated or even removed in future versions. Similar to switch expressions, it may become final and permanent in a future version.
A Record Example
Here’s an example of how a basic record looks like:
We have a
Person record defined in a package with two components:
lastName, and an empty body.
Let’s try to compile it — notice the
How Does it Look Under the Hood?
As mentioned previously, a record is just a class with the purpose of holding and exposing data. Let’s have a look at the generated bytecode with the
Interesting… Several things we can notice:
- The class is marked
final, which means we cannot create a subclass of it.
- The class extends
java.lang.Record, which is the base class for all records, much like
java.lang.Enumis the base class for all enums.
- There are two private final fields named after the two components of the record:
- There is a public constructor that is generated for us:
public examples.Person(java.lang.String, java.lang.String). By looking at its body, it’s easy to see that it just assigns the two arguments to the two fields. The constructor is equivalent to:
- There are two getter methods named
- Three other methods are generated:
equals(). They all rely on
invokedynamicto dynamically invoke the appropriate method containing the implicit implementation. There is a bootstrap method
ObjectMethods.bootstrapthat takes the component names of the record and its getter methods, and generates the methods. Their behaviors is consistent with what we would expect to have:
Adding Member Declarations in Records
We cannot add instance fields to records, which is expected, given that such state should be part of the components. We can, however, add static fields:
We can define static methods and instance methods that can operate on the state of the object:
We can also add constructors, and modify the canonical constructor (the one that takes the two
String parameters). If we want to override the canonical constructor, we can omit the parameters and the assignments to the fields:
Records introduce the capability of properly implementing data classes, without the need to write verbose code. Plain data classes are reduced from several lines of code to a one-liner. There are other language features in progress that work well with records, such as pattern matching. For a much deeper dive into records and background information, see Brian Goetz’s exploratory document on OpenJDK.
Published at DZone with permission of Mahmoud Anouti, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.