Overview
Lombok is an open-source library that is used to reduce boilerplate code in Java classes. This is achieved by replacing many of the repetitive pieces of code with simple and concise annotations.
Lombok injects itself in the build process (via your project/IDE) and auto generates the Bytecode for the desired methods into your .class
files.
So with Lombok, you can get rid of all the getter and setter methods, hash-code, and equals methods and many more just by adding annotations.
Lombok Setup
Installing Lombok into Eclipse
Download the Lombok .jar
file from the official website. Run the downloaded lombok.jar
file or execute the command in the terminal:
java -jar lombok.jar
This will start the installer:
If it didn't automatically detect the location of your preferred IDE, you can specify the location manually and then finish the installation by clicking Install/Update
.
You can check whether the installation is active or not in Eclipse's "About" dialog at the end of the copyright text:
Installing Lombok into NetBeans
Download the Lombok .jar
from the official website and add it to the project libraries.
Activating the plugin is as easy as selecting Project Properties -> Build - Compiling -> Enable Annotation Processing in Editor
.
Installing Lombok into IntelliJ
IntelliJ Idea makes it really easy to install plugins into the IDE:
-
Go to
File -> Settings -> Plugins
and selectBrowse Repositories
-
Search
Lombok Plugin
and clickInstall Plugin
After this, just restart the IDE and you're all set.
For other IDE's you can visit their home page and check the Install section.
Lombok Dependency
We need to add the following dependency in our pom.xml
:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>{version}</version>
<scope>provided</scope>
</dependency>
Note: The scope is provided
as Lombok is a pure build dependency and not a runtime one. This means that we expect the application to provide us with the dependency on runtime.
Lombok Annotations
@Getter and @Setter
These annotations can be used either at a field or class level. If used at the class level, it will generate getters and setters for all the fields in the class:
@Getter
@Setter
public class User {
private String name;
private String email;
}
As seen in the IDE window, both of the fields now have their respective getter and setter methods, even though we didn't actually define them ourselves.
If you want getters/setters for only certain fields, annotate them accordingly:
public class User {
@Getter
@Setter
private String name;
private String email;
}
If you'd like to change the access level of the generated methods and fields, you can do so using the AccessLevel
argument:
@Setter(AccessLevel.PROTECTED)
private String email;
There are a few access levels that Lombok offers in the form of arguments:
- MODULE
- NONE (Represents not generating anything or the complete lack of a method)
- PACKAGE
- PRIVATE
- PROTECTED
- PUBLIC
Constructor Annotations
@AllArgsConstructor
The @AllArgsConstructor
decorator will generate a public constructor will all the fields declared in your class in the same order as they are defined:
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
@AllArgsConstructor
public class User {
private String name;
private String email;
}
The generated constructor would look like:
public User(String name, String email) {
this.name = name;
this.email = email;
}
@NoArgsConstructor
@NoArgsConstructor
will generate a constructor with no arguments:
@NoArgsConstructor
public class User {
private String name;
private String email;
}
The generated constructor would look like:
public User() {}
Note: If the constructor cannot be generated due to the presence of final
fields, an error message will occur.
@RequiredArgsConstructor
@RequiredArgsConstructor
will generate a constructor with all the final
fields in the class:
@RequiredArgsConstructor
public class User {
private final String name;
private String email;
}
The generated constructor would look like:
public User(final String name) {
this.name = name;
}
Note: @NoArgsConstructor
and @RequiredArgsConstructor
can't be used together and will throw a compile time error if you attempt to do so.
@EqualsAndHashCode
@EqualsAndHashCode
can be used at the class level which will generate implementations for equals(Object other)
and hashCode()
methods.
By default, it will use all the non-static and non-transient fields:
@EqualsAndHashCode
public class User {
private String name;
private String email;
private Integer age;
}
If there are certain fields you don't want to include in the equals
or hashCode
methods, then we can exclude those specific fields by using @EqualsAndHashCode.Exclude
:
@EqualsAndHashCode
public class User {
private String name;
private String email;
@EqualsAndHashCode.Exclude
private Integer age;
}
Alternatively, we can specify fields to be included by using @EqualsAndHashCode.Include
and @EqualsAndHashCode(onlyExplicitlyIncluded = true)
:
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class User {
@EqualsAndHashCode.Include
private String name;
@EqualsAndHashCode.Include
private String email;
private Integer age;
}
@ToString
Similarly, @ToString
can be used to generate the toString()
implementation. By default, all non-static fields will be printed. You can specify to include or skip certain fields by using a combination of @ToString.Exclude
, @ToString.Include
, and @ToString(onlyExplicitlyIncluded = true)
just like before:
@ToString(onlyExplicitlyIncluded = true)
public class User {
@ToString.Include
private String name;
@ToString.Include
private String email;
private Integer age;
}
@Data
It's common to have all of the aforementioned annotations in your POJO. Rather than writing an annotation for each of them, Lombok provides an aggregated annotation @Data
.
This bundles the features of @Getter/@Setter
, @EqualsAndHashCode
, @ToString
and @RequiredArgsConstructor
together as if you've stacked them all:
@Data
public class User {
private final String name;
private String email;
}
@Value
Sometimes you want your object to be immutable after their creation. @Value
is an immutable variant of @Data
and is used exactly for this purpose.
By default, all the fields are made final and setters are not created:
@Value
public class User {
private String name;
private String email;
}
@Builder
The Builder pattern is a creational design pattern that is used to help build objects in a step-by-step manner.
As you might already know, while the builder pattern does allow you to instantiate objects in a more verbose and clean way than with constructors, the underlying code needed to implement the pattern is quite convoluted.
@Builder
lets you automatically produce the code required for it:
@Builder
@Data
public class User {
private String name;
private String email;
}
Now you can create the User
object using the Builder pattern without all of the code required to support it:
User user = new User.UserBuilder()
.email("[email protected]")
.name("test name")
.build();
System.out.println(user.getEmail());
Logging
It's common to use loggers in our application and typically we need to initialize a log variable at the top of the class and then use it in our methods.
This can be achieved by @Log
which automatically creates this field:
@Log
public class Test {
public static void main(String[] args) {
log.severe("Log message");
}
}
@Log
creates a log variable with a java.util.logging.Logger.getLogger(LogExample.class.getName())
object.
Lombok supports other logging frameworks too, which can be used by annotations like @Log4j
, @Slf4j
etc.
The full list of supported frameworks can be seen here.
Writing Thread Safe Methods
In Java for multi-threaded applications, we use the synchronized
keyword at critical sections of the code.
We typically use a synchronized
block with an object as a lock:
public class SynchronizedJavaExample {
private static final Object lock = new Object();
public static void test() {
synchronized (lock) {
System.out.println("test");
}
}
}
This can be auto-generated using the @Synchronized
keyword:
public class SynchronizedExample {
@Synchronized
public static void test() {
System.out.println("test");
}
}
Conclusion
In this article, we've provided an introduction to Project Lombok and saw how it eases up our development process by reducing boilerplate code with simple annotations. This drastically enhances readability and brevity.
The code for the examples used in this article can be found on GitHub.