Life got much easier – Using Lombok with Java

After more than 5 years programming in C++, recently I’ve started my first steps programming in Java. There are many differences and I’ll try to share some tips that will make your lives better 🙂

First one is Project Lombok. From their documentation:

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again. Early access to future java features such as val, and much more.

Sounds nice right?
In general this is something that provides annotation that can be used in our code to auto-generate many interesting stuff and save us time so we won’t need to write them.

One example is implementing the builder pattern. As a best practice, when we need to create mutable objects and pass to the constructor many parameters, it can be challenging reading the code afterwards. Imagine a constructor with 10 strings. Mistakes can happen really easily.
The builder pattern simply says – instead of passing all those parameters to the constructor, let’s use a helper class that will define everything we need and then we’ll invoke a method that will create the mutable class for us with everything initialized.

For example, let’s take a simple PhoneBookEntry class which contains the following fields:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class PhoneBookEntry {
    public PhoneBookEntry(final String name, final String email, final String phone, final String address) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.address = address;
    }
   
    public final String name;
    public final String email;
    public final String phone;
    public final String address;
}

We can add a constructor that receives everything and when we’ll want to create a new object it will look like this:

1
PhoneBookEntry entry = new PhoneBookEntry("Alexander", "my@email.com", "0000", "123 MyBlog st.")

When reading this code we can’t really know which parameter goes where and mistakes can happen much easily.

For implementing the pattern we need to create a static inner class that will have public method for each member we want to set, add a static method for creating an instance of this class, and make our constructor private. After the changes, the code should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class PhoneBookEntry {
    public final String name;
    public final String email;
    public final String phone;
    public final String address;

    private PhoneBookEntry(final String name, final String email, final String phone, final String address) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.address = address;
    }
   
    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private String name;
        private String email;
        private String phone;
        private String address;
       
        public Builder withName(final String name) {
            this.name = name;
            return this;
        }
       
        public Builder withEmail(final String email) {
            this.email = email;
            return this;
        }
       
        public Builder withPhone(final String phone) {
            this.phone = phone;
            return this;
        }
       
        public Builder withAddress(final String address) {
            this.address = address;
            return this;
        }
       
        public PhoneBookEntry build() {
            return new PhoneBookEntry(name, email, phone, address);
        }
    }
}

The usage is pretty simple and straight forward:

1
2
3
4
5
6
PhoneBookEntry entry = PhoneBookEntry.builder()
        .withName("Alexander")
        .withEmail("my@email.com")
        .withPhone("0000")
        .withAddress("123 MyBlog st.")
        .build();

You can add validations to the builder and make sure for example that all the arguments were supplied and etc.

The builder pattern is nice and helps the readability of the code but it can take some time implementing it for every object. This is one of the use-cases that I use Lombok for. Instead of writing all this code, I can simply add an annotation:

1
2
3
4
5
6
7
8
9
import lombok.Builder;

@Builder
public class PhoneBookEntry {
    public final String name;
    public final String email;
    public final String phone;
    public final String address;
}

Lombok will generate the builder class automatically and we can use it in the same way as before:

1
2
3
4
5
6
PhoneBookEntry entry = PhoneBookEntry.builder()
        .name("Alexander")
        .email("my@email.com")
        .phone("0000")
        .address("123 MyBlog st.")
        .build();

Another thing that I’ve seen reading Java code is that people prefer keeping the class members private and exposing them to the outside world using get methods. In our example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import lombok.Builder;

@Builder
public class PhoneBookEntry {
    private final String name;
    private final String email;
    private final String phone;
    private final String address;
   
    public String getName() {
        return name;
    }
   
    public String getEmail() {
        return email;
    }
   
    public String getPhone() {
        return phone;
    }
   
    public String getAddress() {
        return address;
    }
}

Again, this can be achieved with a simple annotation:

1
2
3
4
5
6
7
8
9
10
11
import lombok.Builder;
import lombok.Value;

@Builder
@Getter
public class PhoneBookEntry {
    private final String name;
    private final String email;
    private final String phone;
    private final String address;
}

Need to compare between instances of your class ? You can override the equals method the the hashCode() method – or you can simply add the @EqualsAndHashCode annotation and Lombok will take care of it for you.

My advice is before implementing things that are part of a routine and does not contain any business logic or something interesting, before starting writing code, just go to the Lombok features page and check if it’s there already.

– Alexander.