72

I love project Lombok but in these days I'm reading and trying some of the new features of java 14.

Inside the new capability, there is the record keyword that allows creating a class with already built-in the following functionality: constructor, private final fields, accessors, equals/hashCode, getters, toString methods.

Now my question is: is better to rely on the feature of Lombok or should we start using the record functionality:

Is better to use this:

record Person (String name, String surname) {}

or that:

@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Person {
  @Getter private int name;
  @Getter private int surname;
}

What are the pros and cons of the both approach?

gixlg
  • 1,193
  • 1
  • 9
  • 21
  • 6
    For one thing, `record` will not work for things expecting JavaBeans-style getters and setters. – Mark Rotteveel Apr 19 '20 at 15:23
  • 6
    What Rotteveel’s comment means is that the property accessor method on a record is named the same name of the property. So, `alice.phoneNumber()` rather than the JavaBeans convention of prefixing with `get`, as in `alice.getPhoneNumber()`. – Basil Bourque Apr 19 '20 at 15:29
  • 1
    Records have a lot of restrictions compared to classes, a record can't extend an other record or class for instance, check the restrictions section on this JEP https://openjdk.java.net/jeps/359 for further details – Youssef NAIT Apr 19 '20 at 15:36
  • 1
    Your sample is heavily biased toward record. When written without all the fat you added on the old class then the difference is much slimmer: `record Person (String name, String surname) {}` vs: `@Value class Person { int name; int surname; }` More other, just change `@Value` to `@Data` and magically you'll have a non-immutable class compatible with ORMs. Something that is not possible or difficult to achieve with java 17 record. – Zartc Feb 17 '22 at 14:54

6 Answers6

86

Lombok, and the record feature of the Java language, are different tools for different things. There is some superficial overlap, but don't let that distract you.

Lombok is largely about syntactic convenience; it is a macro-processor pre-loaded with some known useful patterns of code. It doesn't confer any semantics; it just automates the patterns, according to some knobs you set in the code with annotations. Lombok is purely about the convenience of implementing data-carrying classes.

Records are a semantic feature; they are nominal tuples. By making a semantic declaration that Point is a tuple of (int x, int y), the compiler can derive its representation, as well as construction, declaration, equality, hashing, and string representation protocols, from this state description. Because they carry semantics, readers and frameworks can also reason with higher confidence about the API of records. (This may also be syntactically convenient; if so, that's great.)

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
  • 1
    +1 Brian Goetz: And that's assuming the you can get the current Lombok version into your IDE. I wonder if Lombok has any meaningful advantage as regards quicker code reading that a class comment would not confer. – Trunk Apr 25 '20 at 18:29
  • I contend that they are not quite named tuples - general tuples don't require any definition. But record types still need to be defined ahead of usage. In C#, this can be done: (string first, string middle, string last) methodThatReturnsATuple() – Solubris Jun 11 '20 at 11:30
  • 5
    @Solubris If you get to define "tuple", then of course you are correct. We had this same debate about whether Java 8 lambdas were "real" closures; this always came down, at some level, to "I think 'closure' means X because that's what it meant in the first language in which I encountered it." But its not a very productive debate. – Brian Goetz Jun 11 '20 at 16:51
  • There are numerous differences to what a sensible definition of a tuple would be so I think its a misleading to associate record types with tuples in anyway. For example: record Point(int x, int y) { } record Offset(int x, int y) { } var p1 = new Point(1, 2); var o1 = new Offset(1, 2); System.out.println(p1.equals(o1)); This prints out false, but this doesn't make sense for tuples.. – Solubris Jun 11 '20 at 21:26
  • 5
    I think that it might have been useful to include a disclaimer of the sort that rzwitserloot did before you, indicating that you were the author of Records (https://openjdk.java.net/jeps/384). You may be biased as to their flexibility and utility as compared to @Value. – user3742898 Mar 04 '21 at 16:06
34

NB: Instead of that christmas tree of annotations, you can just use @Value on the class. Note that this makes the class final, and makes all fields both private and final, and gives you all the rest as well. This is close to what records are (they too are final, and all fields inside are final).

record is still in preview, so for production code, obviously it's not, yet, suitable. Use lombok.

Once records are out of preview, it's more complicated. Lombok is FAR more flexible; you can easily swap in some new aspect without having to rewrite all the code (you can just, for example, add an 'extends' clause to your class without having to then handwrite the equals and hashCode method; something records cannot give you). Lombok also gives you more features: You can for example add a builder by adding the @Builder annotation; not something records can do.

If it's highly unlikely you're going to use any of that for the class you're designing - I'd use records.

DISCLAIMER: I'm a core contributor to Project Lombok.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • 3
    `@Builder` support for records was added in v1.18.22 in October 2021 — https://github.com/projectlombok/lombok/issues/2356 – M. Justin Dec 23 '21 at 03:46
14

I've been playing around with this combination for some time as well and with the slight bit of hands-on I could list down the following differences:

Lombok

  • Records are not yet as powerful a tool to eliminate Lombok all together. Note that the library has much more to offer than just the @Getter, @AllArgsConstructor, @ToString, @EqualsAndHashCode.
  • Experienced by self, the EqualsAndHashCode is not the same as you would expect when it comes to migrating to records.

Records

  • Records are an official part of the language, with support of all major IDEs
  • On a different note, if the requirement of your object representation is to be a "data carrier" you can still seek advantage of Records, without relying on an additional library to reduce the boilerplate code to perform that precisely. That is the reason that as a conclusive note this blog reads the following:

It will also help teams eliminate many hand-coded implementations of the underlying pattern and reduce or remove the need for libraries like Lombok.

Of course, on a day-to-day basis, it is always wise based on the requirements of a project to choose which way to follow and practice.

Brian Goetz
  • 90,105
  • 23
  • 150
  • 161
Naman
  • 27,789
  • 26
  • 218
  • 353
  • Note - I would try to keep this updated with more examples for being a user to use both of them frequently at present. – Naman Apr 19 '20 at 16:11
10

While Brian explains well the different goals of Lombok and records, he does not explain when to use which.

If your class is a "transparent, shallowly immutable data aggregate" then a record will do a great job because:

  1. it has even less ceremony than a class annotated with Lombok
  2. it carries the semantic information "this is an immutable data class" (as emphasized in Brian Goetz's answer). This semantic information may be valuable both to programmers and to frameworks.

I would still use Lombok if your class cannot live with the restrictions of records (e.g. immutability, no builder, not extensible).

Stefan Feuerhahn
  • 1,564
  • 1
  • 14
  • 22
2

Java Records don't require any additional dependency, so it's better to use them instead of Lombok I think.

If your project supports Java 14 you can already use them in Eclipse.

There's a plugin in the marketplace for it:

https://marketplace.eclipse.org/content/java-14-support-eclipse-2020-03-415

Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Laura Liparulo
  • 2,849
  • 26
  • 27
  • Lombok doesn't require any additional dependency on your built code either. Lombok and records both have advantages and disadvantages but an extra dependency is not one of the considerations you should look at. – mjaggard Oct 18 '22 at 12:43
-2

In short, if you are doing functional coding with Java, use records. Otherwise use Lombok, it is much more flexible and powerful.

There are some exceptions to this rule for e.g. in API coding.