
Java, being an object-oriented language, often requires a lot of boilerplate code. We normally write getter, setter, constructors, and toString() methods, which can clutter our classes. This can make the codebase longer, harder to maintain, and more error-prone. Enter Lombok in Java.
Lombok is a library that automatically generates the boilerplate code during compilation. It offers a set of annotations that can eliminate the need for writing repetitive code, making your Java classes cleaner and more maintainable. In this blog, I’ll walk you through how I used Lombok in Java to reduce boilerplate code, with code examples that demonstrate its powerful features.
Table of Contents
ToggleWhy Use Lombok in Java?
Before diving into the examples, let’s first understand why using Lombok is beneficial in Java development:
- Less Boilerplate Code: Lombok reduces the need for manually writing repetitive code like getters, setters, constructors, and equals() methods.
- Cleaner Code: Your class files will contain less code, making them easier to read and maintain.
- Faster Development: By eliminating the need to write boilerplate code, you can focus on the actual business logic.
- Automatic Code Generation: The annotations ensure that the necessary methods are generated at compile-time.
Now, let’s take a look at how we can use Lombok to achieve this.
How to Set Up Lombok in Java
Before we begin with the code examples, make sure Lombok is set up in your project. If you’re using Maven, add the following dependency in your pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
For Gradle, add the following:
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
Ensure that your IDE has the Lombok plugin installed. For example, in IntelliJ IDEA, install the Lombok plugin and enable annotation processing.
1. @Getter and @Setter Annotations
One of the most common use cases in Java is writing getter and setter methods for our class fields. With Lombok, you can eliminate this code by simply adding @Getter
and @Setter
annotations.
Here’s an example:
import lombok.Getter;
import lombok.Setter;
public class User {
@Getter @Setter
private String name;
@Getter @Setter
private int age;
}
Explanation: The @Getter
and @Setter
annotations automatically generate the getName()
, setName()
, getAge()
, and setAge()
methods at compile-time. You no longer need to manually write them!
2. @ToString Annotation
When debugging or logging, seeing a textual representation of an object is often useful. Normally, you’d write a toString()
method, but Lombok simplifies this with the @ToString
annotation.
import lombok.ToString;
@ToString
public class Product {
private String productName;
private double price;
}
Explanation: The @ToString
annotation generates a toString()
method that returns a string containing the field names and values.
3. @NoArgsConstructor and @AllArgsConstructor Annotations
Constructors are another area where a lot of boilerplate code can arise, especially if your class has multiple fields. Lombok offers annotations like @NoArgsConstructor
and @AllArgsConstructor
to automatically generate constructors.
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private String title;
private String author;
}
Explanation: The @NoArgsConstructor
generates a no-argument constructor, while the @AllArgsConstructor
generates a constructor that accepts all fields as arguments.
4. @EqualsAndHashCode Annotation
Overriding the equals()
and hashCode()
methods can be cumbersome. Lombok’s @EqualsAndHashCode
simplifies this by generating the appropriate methods for you.
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class Employee {
private int id;
private String name;
}
Explanation: This will generate equals()
and hashCode()
methods based on the fields of the class. You can also customize which fields to include by using parameters in the annotation.
5. @Data Annotation
If you want to combine multiple Lombok annotations, such as @Getter
, @Setter
, @ToString
, @EqualsAndHashCode
, and @RequiredArgsConstructor
, Lombok provides a convenient annotation: @Data
.
import lombok.Data;
@Data
public class Customer {
private String name;
private String email;
}
Explanation: The @Data
annotation generates getter, setter, toString()
, equals()
, hashCode()
, and a required-arguments constructor, making it a one-stop-shop for reducing boilerplate code.
6. @Builder Annotation
Lombok’s @Builder
annotation is perfect for implementing the Builder design pattern, which allows for flexible object creation, especially when dealing with many optional fields.
import lombok.Builder;
@Builder
public class Car {
private String model;
private String manufacturer;
private int year;
}
Explanation: The @Builder
annotation generates a builder class and methods like Car.builder().model(“Model S”).manufacturer(“Tesla”).year(2022).build();
, which makes object creation more readable.
7. @Value Annotation
In many cases, especially in immutable objects, we want to create read-only fields. Lombok’s @Value
annotation helps you declare such classes easily.
import lombok.Value;
@Value
public class Address {
String street;
String city;
String zipCode;
}
Explanation: The @Value
annotation automatically makes all fields final and creates a constructor, getters, equals()
, hashCode()
, and toString()
methods.
8. @SneakyThrows Annotation
Lombok can also simplify exception handling with the @SneakyThrows
annotation, which allows you to throw checked exceptions without explicitly declaring them.
import lombok.SneakyThrows;
public class FileUtils {
@SneakyThrows
public static void readFile(String fileName) {
java.nio.file.Files.readAllLines(java.nio.file.Path.of(fileName)).forEach(System.out::println);
}
}
Explanation: The @SneakyThrows
annotation allows checked exceptions (like IOException
) to be thrown without a try-catch block.
9. @NonNull Annotation
Lombok also helps with null-checking through the @NonNull
annotation, which generates a NullPointerException
if a null value is passed.
import lombok.NonNull;
public class Person {
public void setName(@NonNull String name) {
this.name = name;
}
private String name;
}
Explanation: If setName(null)
is called, it will throw a NullPointerException
. The @NonNull
annotation provides a simple and automatic way to handle null values in your methods.
10. @Cleanup Annotation
When working with resources like streams or files, you need to manually close them to prevent resource leaks. The @Cleanup
annotation ensures that the resource is automatically closed.
import lombok.Cleanup;
import java.io.*;
public class FileExample {
public void readFile(String filePath) throws IOException {
@Cleanup BufferedReader reader = new BufferedReader(new FileReader(filePath));
System.out.println(reader.readLine());
}
}
Explanation: The @Cleanup
annotation ensures that the BufferedReader is closed after use, saving you from writing the try-finally block.
11. @Accessors Annotation
The @Accessors
annotation customizes how Lombok generates getters and setters. You can control whether methods return this (for chaining) or if the field names should follow a fluent style.
Example:
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
@Getter
@Setter
@Accessors(fluent = true, chain = true)
public class Car {
private String brand;
private String model;
}
Explanation: Now, you can chain setters in a fluent style:
Car car = new Car().brand("Toyota").model("Corolla");
12. @With Annotation
The @With
annotation is used to generate a “with” method, which creates a new object with a single property modified, leaving the rest unchanged. This is particularly useful for immutable objects.
Example:
import lombok.With;
import lombok.Value;
@Value
public class Book {
String title;
@With String author;
}
Explanation: This will allow:
Book book1 = new Book("Effective Java", "Joshua Bloch");
Book book2 = book1.withAuthor("James Gosling");
book2
will be a copy of book1
with the author changed to “James Gosling”
.
13. @Slf4j Annotation
The @Slf4j
annotation automatically creates a logger instance in your class using the Simple Logging Facade for Java (SLF4J) API. This helps you avoid manually creating a logger and allows you to easily log messages.
Example:
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LoggerExample {
public void doSomething() {
log.info("This is an info message");
}
}
Explanation: In this case, Lombok will automatically generate an SLF4J Logger instance named log
.
14. @SuperBuilder Annotation
@SuperBuilder
is an advanced version of @Builder
that supports inheritance. It is useful when building complex object hierarchies.
Example:
import lombok.experimental.SuperBuilder;
@SuperBuilder
class Parent {
private final String parentField;
}
@SuperBuilder
class Child extends Parent {
private final String childField;
}
Explanation: Now, you can build both Parent and Child instances using a builder pattern:
Child child = Child.builder()
.parentField("Parent value")
.childField("Child value")
.build();
15. @ToString.Exclude and @EqualsAndHashCode.Exclude Annotations
These annotations are used to exclude specific fields from being included in the generated toString()
, equals()
, or hashCode()
methods.
Example:
import lombok.Data;
import lombok.ToString;
@Data
public class Employee {
private String name;
@ToString.Exclude
private String sensitiveInfo;
}
Explanation: This will exclude sensitiveInfo
from the toString()
method.
16. @Synchronized Annotation
The @Synchronized
annotation is a replacement for Java’s synchronized keyword. It ensures that a method is thread-safe by locking on a private field.
Example:
import lombok.Synchronized;
public class Task {
@Synchronized
public void performTask() {
// Critical section
}
}
Explanation: This generates a synchronized method, locking on a private lock object (not on this), improving thread-safety.
Real-World Use Case: Using Lombok in a Java Project
Now that we’ve explored the different annotations offered by Lombok in Java, let’s take a look at a simple real-world use case where I can use Lombok to avoid boilerplate code. Suppose we’re working on a project where we need to create a User
class that contains fields like id
, name
, email
, and age
. We want to use all of Lombok’s features to make this class as clean and readable as possible.
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
private int id;
private String name;
private String email;
private int age;
}
Explanation: With just a few lines of code, Lombok generates the following methods and constructors:
- Getters and Setters for all fields (
@Data
) toString()
,equals()
, andhashCode()
methods (@Data
)- A no-argument constructor (
@NoArgsConstructor
) - An all-argument constructor (
@AllArgsConstructor
) - A builder pattern implementation (
@Builder
)
This drastically reduces the length of the class while still providing all the functionality you need!
Conclusion
By leveraging Lombok in Java, you can significantly reduce the amount of boilerplate code you need to write, allowing you to focus more on business logic rather than repetitive tasks like writing getter and setter methods, constructors, and toString()
methods. With its powerful annotations, Lombok offers an elegant solution to make your Java code more concise, maintainable, and less error-prone.
In this blog, we covered several key Lombok annotations like @Getter
, @Setter
, @ToString
, @Data
, @Builder
, and many others that simplify everyday Java development tasks. Each of these annotations comes with its own unique benefits and use cases, and when combined, they allow developers to write cleaner and more readable code.
Whether you’re working on small projects or large-scale applications, Lombok is a tool every Java developer should consider incorporating into their toolkit. By cutting down on boilerplate code, Lombok helps you write better, cleaner, and more maintainable Java code.
If you haven’t yet integrated Lombok in Java into your projects, now’s the time to start and experience the productivity boost that it brings. Your codebase will thank you, and your fellow developers will too!