Lombok: A Comprehensive Guide to Java’s Most Useful Library

What is Lombok and Why Is It So Popular

Project Lombok is a java library that seamlessly integrates with your editor and build tools, enhancing your java.

It improves developer productivity by reducing the amount of boiler plate to be written in your java programs by providing set of annotations.

Instllation

To configure lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code,but does not need to be present when running/testing/jarring/otherwise deploying your code.

Maven

Using lombok with Maven build tool.

<dependencies>
	<dependency>
		<groupId>org.projectlombok</groupId>
		<artifactId>lombok</artifactId>
		<version>1.18.26</version>
		<scope>provided</scope>
	</dependency>
</dependencies>Code language: Java (java)

Gradle

Using lombok with Gradlebuild tool.

repositories {
	mavenCentral()
}

dependencies {
	compileOnly 'org.projectlombok:lombok:1.18.26'
	annotationProcessor 'org.projectlombok:lombok:1.18.26'
	
	testCompileOnly 'org.projectlombok:lombok:1.18.26'
	testAnnotationProcessor 'org.projectlombok:lombok:1.18.26'
}Code language: Java (java)

Using Lombok Annotations

@Getter and @Setter

@Getter and @Setter most useful annotation from the lombok. It frees you from the writing all the getter and setter methods in java classes.

These annotation can be applied at class level and field level.

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class Employee {
    private Integer id;
    private String name;
}Code language: Java (java)

You can also use same annotations at field level

public class Employee {
    @Getter
    @Setter
    private Integer id;
    
    @Getter
    @Setter
    private String name;
}Code language: Java (java)

Field annotations helps us to specify only getter or only setter.

For following code, for id field only getter method is create and for name field only setter method is created.

import lombok.Getter;
import lombok.Setter;

public class Employee1 {
    @Getter    
    private Integer id;

    @Setter
    private String name;
}
Code language: Java (java)

You can also specify the access level for setter/getter method.

In following code, getName will have “protected” access modifier.

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

public class Employee1 {
    @Getter
    private Integer id;

    @Setter(AccessLevel.PROTECTED)
    private String name;
}
Code language: Java (java)

@ToString

When you annotate a class with @ToString, lombok will build an implementation of the toString() function. You can define whether field names should be included using configuration options, but otherwise the structure is fixed: the class name followed by parenthesis holding fields separated by commas, e.g. Employee(id=123, name= “test”).

  • All non-static fields are printed by default
  • If you wish to skip some fields, annotate them with @ToString.Exclude
  • You can also indicate which fields should be included by using @ToString(onlyExplicitlyIncluded = true), then marking each field with @ToString.Include
  • You can change the name used to identify the member with @ToString.Include(name = "some other name")
  •  You can change the order in which the members are printed via @ToString.Include(rank = -1)
import lombok.ToString;


@ToString
public class Employee {

    private static final int STATIC_VAR = 10;
    private Integer id;
    @ToString.Exclude private String name;
}Code language: Java (java)

In above Employee class , ToString method will only include Id field

@EqualsAndHashCode

When you annotate a class with @EqualsAndHashCode,lombok generates the implementations of the equals(Object other) and hashCode() methods.

  • By default, generated methods will use all non-static, non-transient fields
  • You can modify which fields are used by marking type members with @EqualsAndHashCode.Include or @EqualsAndHashCode.Exclude
@EqualsAndHashCode
public class Employee4 {

    private static final int STATIC_VAR = 10;
    private Integer id;
    private String name;

    @EqualsAndHashCode.Exclude
    private String address;

    @EqualsAndHashCode.Exclude
    private double salary;
}Code language: Java (java)

@NonNull

You can use @NonNull on a record component, or a parameter of a method or constructor. This will cause to lombok generate a null-check statement for you.

public class Employee {
    private Integer id;
    private String name;

    public Employee(@NotNull Person person) {
        this.name = person.getName();
    }
}Code language: Java (java)

The above code generates following code

public class Employee {
    private Integer id;
    private String name;

    public Employee(@NotNull Person person) {
      if (person == null) {
        throw new NullPointerException("person is marked non-null but is null");
      }
        this.name = person.getName();
    }
}Code language: Java (java)

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

When you annotate a class with @NoArgsConstructor,lombok generates a constructor with no parameters.

We can specify access modifier of the constructor with access property on the

@NoArgsConstructor
public class Employee {

    private Integer id;

    private String name;

}Code language: Java (java)

The above code generates following constructor

 
public class Employee {

    private Integer id;

    private String name;

    public Employee() {
    }

}Code language: Java (java)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Employee {
    private Integer id;
    private String name;   
    
}Code language: Java (java)
  @NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Employee {
    private Integer id;
    private String name;

    protected Employee() {
    }
    
}Code language: Java (java)

@RequiredArgsConstructor 

@RequiredArgsConstructor creates a constructor with one argument for each field that needs special treatment. All non-initialized final fields receive a parameter, as do any @NonNull fields that aren’t initialised when they are defined. An explicit null check is generated for fields specified with @NonNull. If any of the parameters meant for the fields indicated with @NonNull contain null, the constructor will raise a NullPointerException. The order of the arguments corresponds to the order of the fields in your class.

@RequiredArgsConstructor
public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address;

}Code language: Java (java)

The above code is equivalent to

public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address;

    public Employee(Address address) {
        if (address == null) throw new NullPointerException("Address is null");
        this.address = address;
    }
}
Code language: Java (java)

@AllArgsConstructor 

@AllArgsConstructor generates a constructor with 1 parameter for each field in your class. Fields marked with @NonNull result in null checks on those parameters.

@AllArgsConstructor
public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address;
    
}Code language: Java (java)

The above code is equivalent to

public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address;

    public Employee(Integer id,String name, Address address) {
        if (address == null) throw new NullPointerException("Address is null");
        this.name = name;
        this.id = id;
        this.address = address;
    }
}Code language: Java (java)

@Data

@Data is a handy shortcut annotation that combines the functionality of @ToString, @EqualsAndHashCode, @Getter / @Setter, and @RequiredArgsConstructor: To put it another way, @Data generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate toString, equals, and hashCode implementations that involve the class’s fields, as well as a constructor that initialises all final fields, as well as all non-final fields with no initializer that have been marked with @NonNull

All generated getters and setters will be public. To override the access level, annotate the field or class with an explicit @Setter and/or @Getter annotation. You can also use this annotation (by combining it with AccessLevel.NONE) to suppress generating a getter and/or setter altogether.

import lombok.Data;

@Data
public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address
}
Code language: Java (java)

@Value

@Value is an immutable variation of @Data; by default, all fields are made private and final, and setters are not produced. Because immutability cannot be forced on a subclass, the class itself is likewise marked final by default. Like @Data, handy toString(), equals(), and hashCode() methods are produced, as is a getter method for each field and a constructor that covers every parameter (excluding final fields that are initialized in the field definition).

@Value
public class Employee {
    private Integer id;
    private String name;
    @NotNull
    private Address address;

}Code language: Java (java)

@Builder

The @Builder annotation produces complex builder APIs for your classes.

@Builder
public class Employee {
private Integer id;
private String name;
@NotNull
private Address address;
}

@Builder lets you automatically produce the code required to have your class be instantiable with code such as:

Employee.builder()
             .id(1)
             .name('test')Code language: Java (java)

A method annotated with @Builder (from now on called the target) causes the following 7 things to be generated:

  • An inner static class named FooBuilder, with the same type arguments as the static method (called the builder).
  • In the builder: One private non-static non-final field for each parameter of the target.
  • In the builder: A package private no-args empty constructor.
  • In the builder: A ‘setter’-like method for each parameter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
  • In the builder: A build() method which calls the method, passing in each field. It returns the same type that the target returns.
  • In the builder: A sensible toString() implementation.
  • In the class containing the target: A builder() method, which creates a new instance of the builder.

Similar Posts