Lombok Unleashed: Elevating Java Efficiency with Getters, Setters, Constructors, Builders, and More
Tags: lombok, java
Published: 2024-07-11 07:05:24

## Introduction to Project Lombok

Project Lombok is a popular Java library that aims to reduce boilerplate code and enhance coders productivity by saving lots of time and their energy by providing annotations to automatically generate common Java code during compile time

## What is Project Lombok?

Project Lombok addresses the verbosity of Java by offering annotations that eliminate the need for manually writing repetitive code constructs such as getters, setters, constructors, equals, hashCode, and toString methods. By annotating fields or classes with Lombok annotations, coders can instruct the compiler to generate these methods automatically, reducing the amount of boilerplate code and making Java classes more compact and readable.

## Why are we using Project Lombok ?

Using Project Lombok in Java offers several compelling benefits that contribute to improved productivity, code quality, and maintainability.
Here are a few reasons to choose Project Lombok.
It reduces the “Boilerplate Code”.
It also improves codes reusability and readability.
It is very simple to implement and doesn’t have any complexity.
Integrates easily with “IDEs”.

## How to implement Lombok in Java on a Maven project

Most of our projects are based on Maven. So, we just have to add “Project Lombok” dependencies to our “Pom.xml” file present in our project.

Go to maven repository and copy Lombok Maven repository from there, add the latest lombok dependency in your “Pom.xml” and save it, then refresh the project.

## Getters, Setters feature of Project Lombok in Java

In Java, by far the most common practice is to add getters and setters using the “Java Beans” pattern. Most of the IDEs automatically generate code for these patterns.

Let us see the code understand this approach by creating getter and setter with the help of “Data Objects” and “Data Factory” :

**Data Object without Lombok**

While the traditional JavaBeans approach for creating getter and setter methods manually gets the job done, but it has several drawbacks and limitations that make it less desirable, especially in modern Java development environments all, its drawbacks are majorly covered in the Lombok. 

So, instead of this, we prefer to use the Lombok pattern. Here is how it can be implemented in Java :

## Constructor features of Project Lombok in Java

Constructors without Lombok we have to manually define each constructor, which can be tedious and error-prone, especially for classes with many fields. Additionally, we need to handle various constructor configurations, which can increase the complexity of the code.

Lombok simplifies this process with @NoArgsConstructor, @AllArgsConstructor and @RequiredArgsConstructor annotations. 

**Constructors without Lombok**

Using Lombok annotations reduces the amount of boilerplate code that needs to be written manually. With Lombok, you simply annotate the class and fields, and the constructors are generated automatically based on the specified criteria. This leads to cleaner and more concise code.

## Various Lombok features and properties

1. ToString Generation

- In Java, toString() is a method defined in the java.lang.Object class, which serves the purpose of returning a string representation of an object. The toString() method is inherited by all classes in Java, and its default implementation in the Object class returns a string containing the class name followed by the “at” symbol (@) and the hexadecimal representation of the object’s hash code.
- However, the default implementation of toString() provided by Object may not always be meaningful or useful for specific classes. Therefore, it is common practice for developers to override the toString() method in their own classes to provide a custom string representation that better describes the state or properties of the object.
- As per our example, a Profile class might override toString() to return a string containing the firstName, lastName, designation, age information. Overriding toString() allows to easily print or log object information in a human-readable format, which can be helpful for debugging, logging, or displaying information to users.
- Without using ToString Lombok annotations we’ve to manually implement the toString() method within the Profile class. We concatenate the firstName, lastName, designation, and age fields to create the desired string representation. This manual implementation achieves the same result as Lombok’s @ToString annotation.

**Without using ToString Annotations feature**

- The @ToString annotation generates a toString() method for the class, providing a string representation of its fields. No need to write one ourselves and maintain it as we enrich our data model.
- With this annotation, calling toString() on an instance of profile will return a string containing the values of its fields.
- @Exclude annotations can be useful for every various different annotations like Getters, Setters, ToString, EqualAndHashCode, etc. Let us understand that along with @ToString annotation example.
- By annotating the designation field with @ToString(exclude = {“designation”}) 
- Lombok excludes it from being included in the toString() method generated by @ToString. This can be useful if you want to avoid displaying certain fields in the string representation of an object.

**2. EqualAndHashCode Generation**

- In Java, equals() and hashCode() are two methods commonly used to implement object equality and hash code generation, respectively.
- equals() Method : The equals() method is used to compare two objects for equality. By default, the equals() method provided by the Object class compares object references, meaning it returns true only if the two objects being compared are the same instance in memory. However, it is often necessary to override the equals() method in custom classes to define a meaningful notion of equality based on object attributes.
- hashCode() Method : The hashCode() method is used to generate a hash code value for an object. A hash code is an integer value that represents the state of an object and is typically used in hash-based data structures like hash tables. The hashCode() method is important because it allows objects to be efficiently stored and retrieved in hash-based collections.
- In our example, we’ve manually implemented and override the equals() method to compare the fields of two Profile objects for equality, and the hashCode() method to generate a hash code based on the fields. 
- We use the Objects.equals() method from the java.util.Objects class to compare the fields for equality, and Objects.hash() method to generate the hash code.

**Without using EqualAndHashCode Annotations feature**

- The @EqualsAndHashCode annotation generates equals() and hashCode() methods based on the class’s fields.
- With this annotation, Lombok generates equals() and hashCode() methods using all fields of the class.
- This eliminates the need for manual implementation of these methods, reducing boilerplate code and improving code maintainability.

**3. Data Annotations**
Without using @Data annotations, we manually have to implement the getters, setters and Constructors features into our code.

- Without using Data Annotations feature

- The @Data annotation is a convenient shortcut that bundles @Getter, @Setter, @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode and many more annotations.
-  Using @Data, Lombok automatically generates these methods for us based on the fields declared in the class. This significantly reduces the amount of boilerplate code that we need to write and maintain, making our code more concise and readable.

4. BuilderPattern

- Returning to our Profile example, constructing a new instance necessitates employing a constructor with potentially numerous count of four arguments, a task that becomes unwieldy as we introduce additional attributes to the class.
- Thankfully, Lombok provides a robust solution with its @Builder feature, which facilitates the utilization of the Builder Pattern for creating new instances. Let’s integrate this feature into our Profile class.

package org.example.dataobjects;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@ToString(exclude = {"designation"})
@EqualsAndHashCode
@Builder
@Data
public class Profile {
   private String firstName;
   private String lastName;
   private String designation;
   private int age;

public static void main(String[] args) {

   // Creating an instance of Profile using the builder
   Profile profile = Profile.builder()
           .firstName("Parth")
           .lastName("Kathrotiya")
           .designation("QA Automation Engineer")
           .age(23)
           .build();
   }
}

**Delombok**

- Delombok is a tool provided by Project Lombok that reverses the effects of Lombok’s annotations, essentially “delombokifying” your code. It allows you to convert Java source code containing Lombok annotations into plain Java code by expanding the annotations and replacing them with the corresponding boilerplate code that they would generate.
- The primary purpose of Delombok is to facilitate compatibility and interoperability with environments or tools that do not support Lombok annotations directly. For example, if you need to share your code with developers who do not have Lombok installed in their development environment, or if you want to analyse or refactor Lombok-annotated code using tools that do not understand Lombok annotations, you can use Delombok to convert the code into a form that is understandable and usable in those contexts.
- Delombok can be invoked via the command line or integrated into build tools such as Maven or Gradle. When you run Delombok on your source code, it processes the Java files, expands the Lombok annotations, and generates new Java files without any Lombok annotations. The resulting code is functionally equivalent to the original code but without any dependency on Lombok.
- Overall, Delombok is a useful tool provided by Project Lombok that enhances the interoperability and maintainability of codebases using Lombok annotations, allowing developers to leverage the benefits of Lombok while still ensuring compatibility with a wide range of development environments and tools.

## Conclusion

While this post highlights the features I’ve found most beneficial, Lombok offers a plethora of additional functionalities and customizations.
Lombok’s documentation is an invaluable resource, providing in-depth explanations and examples for each annotation. If you’re intrigued by this post, I urge you to delve deeper into Lombok’s documentation to uncover even more possibilities.
Moreover, the project site offers comprehensive guides on integrating Lombok across various programming environments. Whether you’re using Eclipse, NetBeans, IntelliJ, or others, rest assured that Lombok seamlessly integrates with your workflow. As someone who frequently switches between IDEs, I can attest to Lombok’s versatility and reliability across all platforms.
Overall, Project Lombok offers a comprehensive set of features that streamline Java development, reduce code verbosity, and promote best practices.
Project Lombok offers a comprehensive set of features that streamline Java testing, reduce code verbosity, and promote best practices. By incorporating Lombok builders and Lombok constructors, testers can further simplify their code and improve maintainability.