DEV Community

PythonIsNotASnake
PythonIsNotASnake

Posted on • Edited on

Java records and why you should use them

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

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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:

public record Fraction(double numerator, double denominator) {}
Enter fullscreen mode Exit fullscreen mode

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.

Fraction fractionAsRecord = new Fraction(0.0, 1.0);
Enter fullscreen mode Exit fullscreen mode

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:

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;
  }
}
Enter fullscreen mode Exit fullscreen mode

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

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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

public interface Mathobject {
  public Mathobject divideByTwo();
}
Enter fullscreen mode Exit fullscreen mode

If we let implement our fraction this interface we can rewrite our static method divideByTwo. This looks like this:

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

  @Override
  public Fraction multiplyByTwo() {
    return new Fraction(numerator, denominator * half);
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)