avatarEmanuel Trandafir

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

2950

Abstract

class="hljs-keyword">public</span> Builder <span class="hljs-title function_">firstName</span><span class="hljs-params">(String firstName)</span> { <span class="hljs-built_in">this</span>.firstName = firstName; <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>; }

    <span class="hljs-keyword">public</span> Builder <span class="hljs-title function_">id</span><span class="hljs-params">(Long id)</span> {
        <span class="hljs-built_in">this</span>.id = id;
        <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>;
    }
    <span class="hljs-comment">// same for the other fields</span>

    <span class="hljs-keyword">public</span> User <span class="hljs-title function_">build</span><span class="hljs-params">()</span> {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">User</span>(
          <span class="hljs-built_in">this</span>.firstName, 
          <span class="hljs-built_in">this</span>.lastName, 
          <span class="hljs-built_in">this</span>.id, 
          <span class="hljs-built_in">this</span>.email,
          <span class="hljs-built_in">this</span>.username);
    }
}

}</pre></div><p id="9802">Now, we can instantiate the record like this:</p><div id="9ab0"><pre><span class="hljs-type">User</span> <span class="hljs-variable">user</span> <span class="hljs-operator">=</span> User.builder() .firstName(<span class="hljs-string">"john"</span>) .id(<span class="hljs-number">12374L</span>) .build();</pre></div><p id="4ac8">You may already know Lombok’s <i>@Builder </i>annotation: it’s working for records too!</p><figure id="c6fb"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*seYDwXQrrNdYb__ohipwhw.png"><figcaption></figcaption></figure><p id="6b52">Basically, we can annotate a record class with @Builder and Lombok will generate all the code from the snippet above, for us:</p><figure id="f4f3"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*N_Pspmhd52dRjx8ffyK9-w.png"><figcaption></figcaption></figure><h1 id="8e86">@NonNull</h1><p id="d9c5">When using records, we can make sure a field is not null by manually checking it inside the constructor:</p><div id="78c9"><pre><span class="hljs-keyword">public</span> record <span class="hljs-title class_">User</span>( <span class="hljs-title class_">String</span> firstName, <span class="hljs-title class_">String</span> lastName, <span class="hljs-title class_">Long</span> id, <span class="hljs-title class_">String</span> email, <span class="hljs-title class_">String</span> username) {

<span class="hljs-title class_">User</span>(<span class="hljs-title class_">String</span> firstName, <span class="hljs-title class_">String</span> lastName, <span class="hljs-title class_">Long</s

Options

pan> id, <span class="hljs-title class_">String</span> email, <span class="hljs-title class_">String</span> username) { <span class="hljs-keyword">if</span> (firstName == <span class="hljs-literal">null</span>) { <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">IllegalArgumentException</span>(<span class="hljs-string">"'firstName' cannot be null!"</span>); } <span class="hljs-variable language_">this</span>.<span class="hljs-property">firstName</span> = firstName; <span class="hljs-variable language_">this</span>.<span class="hljs-property">lastName</span> = lastName; <span class="hljs-variable language_">this</span>.<span class="hljs-property">id</span> = id; <span class="hljs-variable language_">this</span>.<span class="hljs-property">email</span> = email; <span class="hljs-variable language_">this</span>.<span class="hljs-property">username</span> = username; } }</pre></div><p id="7ae2">Because the validation is made in the constructor and the object is immutable, we can be sure the object will always be in a valid state — even if we create it using a builder or if we add <i>with</i>-ers.</p><figure id="1178"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*gF3eB78kt4g6yKEpgf-OGQ.png"><figcaption></figcaption></figure><p id="fc30">Lombok’s @<i>NonNull </i>comes in handy for this. We can annotate the mandatory fields with this annotation and Lombok will do its magic:</p><figure id="53c3"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*bD6sL6YoNyALchtfpO1dCA.png"><figcaption></figcaption></figure><h1 id="5267">Conclusion</h1><p id="295d">In this article, we discussed the Lombok annotations that play nicely with immutable objects and with the new record type.</p><p id="a931">We learned that we can use <i>@With</i> to create new instances of the record, with modified fields.</p><p id="983c">After that, we saw that the already familiar <i>@Builder </i>annotation makes perfect sense for the record objects as well.</p><p id="458c">Finally, we discussed Lombok’s <i>@NonNull</i> which can help us guard against invalid data being passed into the constructor.</p><h1 id="b0d1">Thank You!</h1><p id="5110">Thanks for reading the article and please let me know what you think! Any feedback is welcome.</p><p id="258d">If you want to read more about clean code, design, unit testing, functional programming, and many others, make sure to check out <a href="https://readmedium.com/start-here-6d2b065a626">my other articles</a>.</p><p id="4a2e">If you like my content, consider <a href="https://medium.com/@emanueltrandafir">following or subscribing</a> to the email list.</p><p id="0159">Finally, if you consider becoming a Medium member and supporting my blog, here’s my <a href="https://medium.com/@emanueltrandafir/membership">referral</a>.</p><p id="d77d">Happy Coding!</p></article></body>

These 3 Lombok Annotations Might Skyrocket In Popularity After Java 17 Migration

Let’s discuss Lombok’s @With, @Builder, and @NonNull annotations and see how we can use them with Java 17 records.

@With

Even though records are immutable objects, sometimes we might need to change the attributes of an object.

To solve this, we can create a new instance of the object and copy all the old values, except for the one that needs to be changed. Our method will return a new instance with the modified field and the old instance will not be affected:

If we add a similar “with” method for one or two other fields, we can already imagine the boilerplate code piling up.

Fortunately enough, we can use Lombok’s @With to generate the these methods:

@Builder

Instantiating bigger record objects with nullable fields might be troublesome: Passing “null” is a known code smell regardless if it is done to call a method or to instantiate an object.

We avoid cluttering the code with the use of the builder design pattern:

public record User(
  String firstName, 
  String lastName, 
  Long id, 
  String email, 
  String username) {

    public static User.Builder builder() {
        return new Builder();
    }

    static class Builder {
        String firstName;
        String lastName;
        Long id;
        String email;
        String username;

        public Builder firstName(String firstName) {
            this.firstName = firstName;
            return this;
        }

        public Builder id(Long id) {
            this.id = id;
            return this;
        }
        // same for the other fields

        public User build() {
            return new User(
              this.firstName, 
              this.lastName, 
              this.id, 
              this.email,
              this.username);
        }
    }

}

Now, we can instantiate the record like this:

User user = User.builder()
   .firstName("john")
   .id(12374L)
   .build();

You may already know Lombok’s @Builder annotation: it’s working for records too!

Basically, we can annotate a record class with @Builder and Lombok will generate all the code from the snippet above, for us:

@NonNull

When using records, we can make sure a field is not null by manually checking it inside the constructor:

public record User(
  String firstName,
  String lastName,
  Long id,
  String email,
  String username) {

  User(String firstName, String lastName, Long id, String email, String username) {
    if (firstName == null) {
      throw new IllegalArgumentException("'firstName' cannot be null!");
    }
    this.firstName = firstName;
    this.lastName = lastName;
    this.id = id;
    this.email = email;
    this.username = username;
  }
}

Because the validation is made in the constructor and the object is immutable, we can be sure the object will always be in a valid state — even if we create it using a builder or if we add with-ers.

Lombok’s @NonNull comes in handy for this. We can annotate the mandatory fields with this annotation and Lombok will do its magic:

Conclusion

In this article, we discussed the Lombok annotations that play nicely with immutable objects and with the new record type.

We learned that we can use @With to create new instances of the record, with modified fields.

After that, we saw that the already familiar @Builder annotation makes perfect sense for the record objects as well.

Finally, we discussed Lombok’s @NonNull which can help us guard against invalid data being passed into the constructor.

Thank You!

Thanks for reading the article and please let me know what you think! Any feedback is welcome.

If you want to read more about clean code, design, unit testing, functional programming, and many others, make sure to check out my other articles.

If you like my content, consider following or subscribing to the email list.

Finally, if you consider becoming a Medium member and supporting my blog, here’s my referral.

Happy Coding!

Java8
Java
Programming
Clean Code
Software Development
Recommended from ReadMedium