Java records and why you should use them
Tags: java, beginners
Published: 2023-05-15 19:26:42

If you are a beginner in learning java you have heard of the basics like classes, methods, enums and so on. But since java 16 records are permanently added to the java feature set. This short tutorial will give you explanation what records in java are and some tips how to use them in your next project.
All informations in this tutorial are from the [java 16 records documentation](https://docs.oracle.com/en/java/javase/16/language/records.html) and my own experience.

## What are records?
Easily explained records are an abstraction of java beans. A record defines automatically an all arguments constructor and give public access to all properties of the record. A record does not have any other methods. It is only a _stupid_ java object without any functionality.

## How to implement a record
Similar to enums a record can be part of a java class or a file by its own.
As example we want to define a fraction. A fraction consists of a numerator and a denominator. If we want to write it as a classic java class it would look like this:

```java
public class Fraction {
  private double numerator;
  private double denominator;

  public Fraction() {
    this.numerator = 0.0;
    this.denominator = 1.0;
  }

  public Fraction(double numerator, double denominator) {
    this.numerator = numerator;
    this.denominator = denominator;
  }

  public void setNumerator(double numerator) {
    this.numerator = numerator;
  }

  public double getNumerator() {
    return this.numerator;
  }

  public void setDenominator(double denominator) {
    this.denominator= denominator;
  }

  public double getDenominator() {
    return this.denominator;
  }
}
```
As you can see this is many code only to define a class with two attributes. And now let us see how this will be look as a record:

```java
public record Fraction(double numerator, double denominator) {}
```
Short right? And this is the most important reason to use records. This single line bundles a all arguments constructor and the two public attributes numerator and denominator.
If you want to create a new instance of this record you will do this as you do it for regular classes.

```java
Fraction fractionAsRecord = new Fraction(0.0, 1.0);
```

## Override constructor and getter/setter
If the default constructor and getter/setter methods do not match your use case you can override them. For a constructor you will do it like this:

```java
public record Fraction(double numerator, double denominator) {
  public Fraction(double numerator, double denominator) {
    if (numerator == 0 && denominator == 0) {
      throw new java.lang.IllegalArgumentException(
        "Invalid fraction: " + numerator + "/" + denominator
      );
    }
    this.numerator = numerator;
    this.denominator = denominator;
  }
}
```
How you can see it does not need the override annotation as usual. The same can be done with the methods `double numerator()` or `void numerator(double numerator)`.

## Static attributes and methods
Now we came to a advanced function of records. Records give you the ability to define static attributes and static methods.
For our example we want to divide our fraction with the number two. So we can declare a static attribute `static double half = 2.0` and a static method `static Fraction divideByTwo(Fraction fr)`.

```java
public record Fraction(double numerator, double denominator) {
  static double half = 2;

  public static Fraction divideByTwo(Fraction fr) {
    return new Fraction(fr.numerator(), fr.denominator() * half);
  }
}
```
The method above can be called by `Fraction.divideByTwo(fraction)`. As you can see you can expand records with your needed methods as long as they are static. This will give you a little more flexibility in use of records.

## Other useful features
In the [java 16 documentation](https://docs.oracle.com/en/java/javase/16/language/records.html) are a number of advanced features that I will mention but not explain in all details. You can find them in the link above under the section "Features of Record Classes".
Personally the aspect to let a record implement some interfaces is the most useful for me. For example you can define some basic methods for a group of records. I give you an easy example with the interface `Mathobject`:

```java
public interface Mathobject {
  public Mathobject divideByTwo();
}
```
If we let implement our fraction this interface we can rewrite our static method `divideByTwo`. This looks like this:

```java
public record Fraction(double numerator, double denominator) implements Mathobject {
  static double half = 2;

  @Override
  public Fraction multiplyByTwo() {
    return new Fraction(numerator, denominator * half);
  }
}
```
The record override the method of the interface `Mathobject` and let us use the two attributes from fraction directly inside of the method because this is a non-static method.

## Conclusion
What makes records so useful at the end?
They produce significantly less boilerplate code.
Every experience java developer knows records and can understand the short code very easily. So it makes your code more understandable and cleaner.
And the much important aspect of all is the significantly less code to write which save you time.

Keep coding.

[Hier gelangst du zur deutschen Fassung.](https://dev.to/pythonisnotasnake/java-records-und-wieso-du-sie-nutzen-solltest-german-g9g)