🚀 Java 14 Records 💾 (Preview)
Tags: java, jdk, java14, records
Published: 2020-04-17 10:25:15

---
title: 🚀 Java 14 Records 💾 (Preview)
description: Java 14 Record is a new kind of type declaration in the Java language. Like an enum, a record is a restricted form of class. It declares its representation and commits to an API that matches that representation.
tags: java, jdk, java14, records
cover_image: https://carloschac.in/public/images/java-records.png
canonical_url: https://carloschac.in/2020/04/17/java-records/
series: JDK 14 Records
published: true
---

## 🏁 Records 💾

**Record** is a new kind of type declaration in the Java language. Like an _enum_, a _record_ is a restricted form of class. It declares its representation and commits to an API that matches that representation. Records give up a freedom that classes usually enjoy: the ability to decouple API from representation. In return, records gain a significant degree of concision.

A record has a name and a state description. The state description declares the components of the record. Optionally, a record has a body. For example:

```java
record Point(int x, int y) { }
```

## Let's get started

### ⬇️ Download OpenJDK 14.0.1

- [Linux / x64](https://download.java.net/java/GA/jdk14.0.1/664493ef4a6946b186ff29eb326336a2/7/GPL/openjdk-14.0.1_linux-x64_bin.tar.gz)
- [macOS / x64](https://download.java.net/java/GA/jdk14.0.1/664493ef4a6946b186ff29eb326336a2/7/GPL/openjdk-14.0.1_osx-x64_bin.tar.gz)
- [Windows / x64](https://download.java.net/java/GA/jdk14.0.1/664493ef4a6946b186ff29eb326336a2/7/GPL/openjdk-14.0.1_windows-x64_bin.zip)

### 🚥 Set the JAVA_HOME to point to the downloaded JDK 14

```bash
$ export JAVA_HOME=/path/to/jdk14
$ export PATH=$JAVA_HOME/bin:$PATH
```

### 🚀 Writing our first Java Record 💾

```java
public record Person(
    String firstName,
    String lastName,
    String address,
    LocalDate birthday,
    List<String> achievements) {
}
```


### 💻 Compile it with `javac`

```bash
$ javac --enable-preview -source 14 Person.java  
```

### 💻 Compile it with `maven`

Add the following configuration for the compiler plugin in your `pom.xml`

```xml
<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <release>14</release>
        <compilerArgs>--enable-preview</compilerArgs>
    </configuration>
</plugin>
```

```bash
$ mvn compile
```

### 🚧 What's generated by the compiler?

```bash
$ javap -p Person.class
```

```java
public final class Person extends java.lang.Record {
  private final java.lang.String firstName;
  private final java.lang.String lastName;
  private final java.lang.String address;
  private final java.time.LocalDate birthday;
  private final java.util.List<java.lang.String> achievements;
  public Person(java.lang.String, java.lang.String, java.lang.String, java.time.LocalDate, java.util.List<java.lang.String>);
  public java.lang.String toString();
  public final int hashCode();
  public final boolean equals(java.lang.Object);
  public java.lang.String firstName();
  public java.lang.String lastName();
  public java.lang.String address();
  public java.time.LocalDate birthday();
  public java.util.List<java.lang.String> achievements();
}
```

Because records make the semantic claim of being simple, transparent holders for their data, a record acquires many standard members automatically:

- A private final field for each component of the state description;
- A public read accessor method for each element of the state description, with the same name and type as the component;
- A public constructor, whose signature is the same as the state description, which initializes each field from the corresponding argument;
- Implementations of equals and hashCode that say two records are equal if they are of the same type and contain the same state; and
- An implementation of toString that includes the string representation of all the record components, with their names.

## ⚠️ Shallowly Immutable Data

Similarly to the tests that we did in the article [Immutables/AutoValue/Lombok Which One?](https://carloschac.in/2020/04/12/immutables-autovalue-lombok/) where we check the default behavior in terms of immutability for those libraries, with the below test we demonstrate the statement mentioned in the [JEP 359: Records](https://openjdk.java.net/jeps/359):

> Records provide a compact syntax for declaring classes, which are transparent holders for **shallowly immutable data**.

#### 📐 Test Immutability

```java
@Test
void immutability() {
    // Create a mutable list with 1 element
    var achievements1 = new ArrayList<String>();
    achievements1.add("Speaker");
    achievements1.add("Blogger");
    var achievements2 = List.of("Speaker", "Blogger");


    // Create person 1, assigning the list1
    var person1 = new Person(
            "John",
            "Doe",
            "USA",
            LocalDate.of(1990, 11, 11),
            achievements1
    );

    // Create person 2, assigning the list2
    var person2 = new Person(
            "John",
            "Doe",
            "USA",
            LocalDate.of(1990, 11, 11),
            achievements2
    );

    // Compare the 2 objects
    // Test passes since the fields contain the same values
    assertThat(person1).isEqualTo(person2);

    // Mutate the list used on Model 1
    achievements1.add("AnotherValue");

    // Compare the 2 objects:
    // - PASSES objects are NOT EQUAL for Records 😮 🔴
    assertThat(person1).isNotEqualTo(person2);
}
```

There are two ways of guaranteeing immutability when using records with mutable data types in their signature or when the data type is an interface, and we are not sure about the implementation, i.e., `java.util.Date` or `java.util.List`

1) Create a safe copy of the data type in the record's constructor.
2) Pass only immutable objects when creating the records.

## 🔆 Conclusions

- ✅ _Records_ can reduce several lines of code to a one-liner.
- ✅ With JDK 14, we can prescind of using some code generation libraries to minimize boilerplate code.
- ✅ A great option for:
  - 🔝 Tree nodes
  - 🔝 DTOs
  - 🔝 Compound map keys
  - 🔝 Messages
  - 🔝 Value wrappers
  - 🔝 Discriminated Entities
- ⚠️ _Records_ are only **Shallowly Immutables**, which means that we have to take into consideration the data types passed to them if we want to guarantee immutability.
- ⚠️ _Records_ are a preview language feature, and it is not yet a standard in the JDK.

Related article:

{% post cchacin/immutables-autovalue-lombok-which-one-2j33 %}