Lombok – Theoretical Introduction

In the world of Java, there are many tools and libraries designed to make developers’ lives easier. One such tool is Lombok—a framework that has sparked both admiration and controversy for years.

For some, it’s a must-have that significantly streamlines everyday work; for others, it’s a tool that interferes too much with the code, hiding what happens “under the hood.” Regardless of where you stand in this debate, one thing is certain: Lombok is a library worth a closer look.

This article is intended for Java developers, regardless of their experience level, who want to better understand how Lombok works. If you’re a professional programmer, this series will help you consciously evaluate whether Lombok is worth using in your project by analyzing its advantages and potential drawbacks.

This is the first of two articles where we’ll delve into Lombok—its functionality, benefits, and limitations. We’ll start with the basics: what Lombok is, how it works, and the benefits it can provide to developers who face repetitive code on a daily basis. In this article, we’ll introduce you to the theoretical foundations of Lombok and demonstrate practical examples of its application. You’ll understand why this tool is so commonly used in both commercial and open-source projects.

In the next article, we’ll explore Lombok’s darker side. We’ll discuss the controversies surrounding its use, potential problems that may arise when combined with the latest frameworks (e.g., Spring or Hibernate), and new Java features such as records. We’ll also consider why some developers choose to avoid it and whether, in 2024, Lombok is still a tool worth using.

The goal of this series is to provide a comprehensive view of Lombok—both its strengths and weaknesses. After reading both articles, you’ll be equipped to make an informed decision about whether Lombok is a tool that fits your project.

 

A Bit of Theory

Java is a well-established language in the programming world, but its structure often requires developers to write a lot of code that, while technically necessary, doesn’t contribute much to the application’s logic. This repetitive and unavoidable code is known as boilerplate code.

Imagine a class that stores user data, such as a first name, last name, and age. To make such a class useful in most projects, you would need to write methods to retrieve and update these data fields (getters and setters), create a constructor to initialize the object, and perhaps also implement methods like equals(), hashCode(), and toString(). While these methods are essential for the proper functioning of an application, they often clutter the code. They are just mechanics that need to be done to ensure the program adheres to the principle of encapsulation.

The problem is that this code is often repetitive—it looks nearly identical in every new class. This leads to longer source files that are harder to maintain and read. Now, imagine a project with dozens or even hundreds of such classes. The amount of repetitive code quickly becomes overwhelming.

This is where Lombok comes in—a tool created to eliminate this issue. Instead of manually writing all these methods, you can simply add the appropriate Lombok annotations, and the library takes care of the rest. This way, you get a class that is clean, readable, and contains only what’s truly essential—fields and a few annotations.

But Lombok is more than just a collection of handy annotations. It’s a tool that transforms how you write code in Java, saving time and reducing errors. Thanks to its annotation processor mechanism, which operates during code compilation, Lombok modifies the class “under the hood.” As a result, in the compiled code, you’ll find all the methods you would normally have to write manually, but in the source code, they are absent—they’re generated automatically.

This approach allows developers to focus on actual business logic rather than wasting time on writing repetitive constructs.

 

The Most Popular Annotations

@Getter and @Setter

The annotations @Getter and @Setter generate getter and setter methods for class fields, saving you from manually writing these methods, which in 99% of cases look identical across different classes.

Code without Lombok:

Code without getter and setter

Code with Lombok:

Code with getter and setter

@ToString

The @ToString annotation generates a toString() method for the class, which outputs its fields. This is particularly useful for logging or debugging objects. Additionally, @ToString allows customization, such as excluding certain fields (exclude) or specifying whether static and final fields should be included.

If you usually generate this method using an IDE, Lombok can be more convenient. IDE-generated methods need manual updates, while this annotation automatically updates the toString() method when fields in your class change.

Without Lombok:

without lombok to string

Code with Lombok:

To string with lombok

@EqualsAndHashCode

The @EqualsAndHashCode annotation generates equals() and hashCode() methods based on the class fields. These methods are crucial for comparing objects and using them in structures like HashSet or HashMap. By default, Lombok includes all fields, but you can specify which fields to include or exclude.

Code without Lombok:

code without lombok

Code with Lombok:

code with lombok

@Data

The @Data annotation is an “all-in-one” solution. It combines the functionalities of @Getter, @Setter, @ToString, @EqualsAndHashCode, and @RequiredArgsConstructor. It’s perfect for simple data classes (e.g., DTOs or database models) that need basic methods.

Code without Lombok:

lombok 7

Code with Lombok:

lombok 8

@Builder

The @Builder annotation implements the Builder design pattern, enabling flexible and readable object creation. This is especially useful for classes with many fields that aren’t always required.

Code without Lombok:

lombok 9

Code with Lombok:

lombok 10

@NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor

These annotations generate different types of constructors:

  • @NoArgsConstructor – A no-arguments constructor.
  • @AllArgsConstructor – A constructor with all fields as parameters.
  • @RequiredArgsConstructor – A constructor for fields marked as final or @NonNull.

Code without Lombok:

lombok 11

Code with Lombok:

lombok 12

The above annotations are just a few of the many available in Lombok. As demonstrated, even these can significantly simplify code, making it more concise and readable.

 

Lombok “Under the Hood”

To achieve automatic generation of repetitive code in Java, Lombok operates during the code compilation phase, utilizing the annotation processor mechanism and abstract syntax tree (AST) modification. Let’s take a closer look at how it all works step by step.

To better understand how Lombok works under the hood, it’s worth following the entire process step by step, from writing the source code to generating the final class. Lombok uses mechanisms built into the Java compiler, such as the annotation processor and AST modification, to automatically generate methods that would otherwise need to be written manually. Here’s how the entire process unfolds:

process13

Everything begins with the source code. When a developer writes a class and marks it with Lombok annotations such as @Getter, @Setter, or @Data, the code at this stage is very concise—it primarily contains fields and annotations. The methods that will be generated by Lombok are not visible in the source code. For example, a class with the @Data annotation looks very simple, but it “tells” Lombok to add getters, setters, toString(), equals(), and hashCode() to it.

When the Java compiler (javac) starts analyzing the code, it encounters these annotations. At this moment, Lombok’s annotation processor is triggered. The processor acts as a tool that carefully examines the source code, identifies the fields, and checks which annotations have been used. Based on this information, the processor decides which methods need to be added. For example, if the class has a @Getter annotation, the processor knows it must generate a method that allows reading the value of each field.

Next comes the AST (Abstract Syntax Tree) modification stage. AST is the compiler’s internal representation of the code. It’s like a map that shows what elements are in the class—fields, methods, annotations, etc. Lombok modifies this syntax tree by adding the missing elements, such as getters, setters, or constructors. Although these methods are not visible in the source code, they become an integral part of the class structure at this stage.

After making changes to the AST, the compiler generates a .class file. This is JVM bytecode, which can be read and executed by the Java Virtual Machine (JVM). This file contains all the methods that Lombok has automatically generated. For the JVM and other tools, such as frameworks or tests, the class appears as if all these methods had been written manually by the developer. In practice, this means that a lot of time is saved on writing repetitive code.

Thanks to this approach, Lombok allows significant code simplification while maintaining full performance and application functionality. You don’t have to worry about writing repetitive methods or about forgetting to add one after making changes to the class—Lombok generates them automatically at compile time.

Thanks to Lombok’s collaboration with popular IDEs like IntelliJ IDEA or Eclipse, you can also see the generated methods in autocomplete suggestions and during debugging. IDEs use plugins that “understand” Lombok and can show its effects even if all methods are not visible in the source code.

 

Advantages

Reduction of Repetitive Code
Lombok eliminates the need to manually create repetitive methods like getters, setters, or constructors. Instead of writing dozens of lines of code, you can use a single annotation, such as @Data or @Getter, and all these elements will be automatically generated during compilation. In large projects, where model classes make up the majority of the code, this reduction can significantly enhance readability and productivity.

Improved Readability and Maintainability
Source code in Java with Lombok is much clearer. By eliminating auxiliary methods, classes contain only the essential elements, such as fields and business logic. This makes it easier for new team members to understand the project quickly, and code changes are simpler to implement. Additionally, if a new field is added to a class, Lombok automatically includes it in the generated methods, such as equals() or toString(), reducing the risk of errors.

Time Savings and Reduced Error Risk
Writing auxiliary methods not only takes time but also increases the risk of errors, such as typos, omitting a field in the equals() method, or incorrectly generating hashCode(). Lombok generates these methods consistently and in line with best practices, minimizing the possibility of mistakes. This allows developers to focus on creating actual application logic instead of dealing with repetitive tasks.

Integration with Frameworks
Lombok works seamlessly with popular frameworks such as Spring and Hibernate, which require getters, setters, and constructors. With annotations like @NoArgsConstructor or @AllArgsConstructor, you can quickly create classes that meet the requirements of these frameworks, significantly speeding up integration and reducing the amount of code needed in a project.

Support for the Builder Design Pattern
Lombok facilitates the use of one of the most popular design patterns, the “Builder” pattern. With the @Builder annotation, you can easily generate builder classes that are especially useful in scenarios where objects have many fields, and their configuration requires flexibility. This saves time and ensures more readable code.

 

Summary

Lombok is a tool that changes the way code is written in Java, eliminating redundancy and increasing developer efficiency. By automating the generation of getters, setters, constructors, and other helper methods, Lombok allows developers to focus on the key aspects of the application, such as business logic. Thanks to its advanced mechanism working during the compilation phase, Lombok ensures code clarity and readability while maintaining full functionality. In this article, we described the numerous advantages of this tool, but like any tool, Lombok also has limitations. In the next post, we will describe in more detail the issues and controversies related to its use in large commercial projects.

Written by
Leszek Kukiełka