Introduction
In this tutorial we will see how to use lombok in Java based projects or applications to reduce boilerplate code. Lombok is a Java library that automatically provides getters/setters or equals method in your Java class. Just by placing an annotation your class has a fully featured builder, it automates your logging variables, and much more. You can also use on your any Java based project including Spring based projects.
In java programming lots of boilerplate code are repeated in many parts of the application with little alteration. Lombok aims to replace such worst offenders with a simple set of annotations. The annotations are not used to generate the code but directly utilized by the application.
Prerequisites
Java 8 or 12, Gradle 5.6, Eclipse 4.12, lombok jar, Windows 10 64 bit
Lombok Installation
You need to first install the lombok into Windows machine.
- First get the jar file from the link.
- Put this downloaded jar into any location.
- Open command prompt and navigate to the jar directory and execute the command
java -jar lombok.jar
. You can also run the jar file by double-clicking on it. - Next a window will appear as shown in the below image. It scans your system and look for the IDE. For me it got Eclipde IDE.

- Now simply click “Install/Update”.
- You will see installation successful:

- You are done with lombok installation. In order to take the changes effect into your IDE you need to restart your Eclipse.
Creating Project
Create a gradle based project in Eclipse. The project name is java-lombok-example.
Build Script
Update the build.gradle script to include the required dependency lombok.
plugins {
id 'java-library'
}
sourceCompatibility = 12
targetCompatibility = 12
repositories {
mavenCentral()
maven {
url "http://projectlombok.org/mavenrepo"
}
}
dependencies {
implementation('org.projectlombok:lombok:1.18.10')
}
Examples on Various Annotations
We will see here different operations even without generating the methods which are directly provided by Project Lombok.
For example, a Java project may require hundreds of lines of boilerplate code for defining simple data classes. These classes generally contain a number of fields, getters and setters for those fields, as well as equals()
and hashCode()
implementations. In simple scenarios, Project Lombok can reduce these classes to the required fields and a single @Data
annotation.
@Data
@Data
annotation will provide the getters and setters for your class. You need to put this annotation on a class level.
Create a class called User and annotate with @Data
:
package com.roytuts.java.lombok.example.model;
import lombok.Data;
@Data
public class User {
private String name;
private String email;
}
Now if you see the Outline view in Eclipse then you will see many methods are provided by lombok.

Next we will test the above class by setting the properties using setters and printing the properties thereafter using toString()
method.
package com.roytuts.java.lombok.example;
import com.roytuts.java.lombok.example.model.User;
public class JavaLombokTest {
public static void main(String[] args) {
User user = new User();
user.setName("Soumitra");
user.setEmail("soumitra@email.com");
System.out.println(user);
}
}
Running the above main class will give you below output:
User(name=Soumitra, email=soumitra@email.com)
@Getter, @Setter
Using @Data
annotation we have seen many methods are provided by lombok. Therefore you may not need all these methods and you need only @Getter
and @Setter
methods, then you need to use @Getter
and @Setter
annotations. If you need only getters then use @Getter
annotation and if you need only setters then you @Setter
annotation.

Now if you run the main class again you will get below output:
com.roytuts.java.lombok.example.model.User@4517d9a3
As there is no toString()
method provided by lombok in the above User
class, so you will get the above output of object.
You can even specify the access level of @Getter
and/or @Setter
:
@Setter(AccessLevel.PROTECTED)
You can even specify @Getter
and/or @Setter
on individual attribute:
@Getter
private String name;
@Getter
@Setter
private String email;
@NonNull
@NonNull
annotation is used for fast-fail null check on a particular Java attribute.
When placed on a field or attribute, Lombok will generate a setter method with a null check that will result in a NullPointerException
when you try to set null value to the field or attribute. Additionally, if Lombok generates a constructor for the class then the field will be added to the constructor signature and the null check will be included in the generated constructor code.
You can place this annotation or a class level or field level. Class level annotation will set null check for all fields or attributes. Field or attribute level annotation will set null for that particular field.
For example, consider the below example:

Now try to set the value null
to email field:
package com.roytuts.java.lombok.example;
import com.roytuts.java.lombok.example.model.User;
public class JavaLombokTest {
public static void main(String[] args) {
User user = new User();
user.setName("Soumitra");
user.setEmail(null);
System.out.println(user.getEmail());
}
}
Running the above main class will throw below exception:
Exception in thread "main" java.lang.NullPointerException: email is marked non-null but is null
at com.roytuts.java.lombok.example.model.User.setEmail(User.java:8)
at com.roytuts.java.lombok.example.JavaLombokTest.main(JavaLombokTest.java:12)
@ToString
From the name of the annotation it is obvious that it provides the implementation of toString()
method.
By default, any non-static fields will be included in the output of the method in name-value pairs. You may suppress the names of the properties or fields in the output by setting the annotation parameter includeFieldNames
to false.
Specific fields can be excluded from the output of the generated method by including their field names in the exclude
parameter.
Alternatively, you can use of
parameter to list only those fields which are desired in the output. The output of the toString()
method of a superclass can also be included by setting the callSuper
parameter to true.

Include only fields which you need to include in toString()
output. For example, in the below class I have included only name and email.
package com.roytuts.java.lombok.example.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(of = { "name", "email" })
public class User {
private String name;
private String email;
private String address;
}
Test the above example:
package com.roytuts.java.lombok.example;
import com.roytuts.java.lombok.example.model.User;
public class JavaLombokTest {
public static void main(String[] args) {
User user = new User();
user.setName("Soumitra");
user.setEmail("soumitra@email.com");
user.setAddress("Earth");
System.out.println(user);
}
}
Running the above class will give you below output:
User(name=Soumitra, email=soumitra@email.com)
You can exclude using the exclude parameter:
@ToString(exclude = { "address" })
To exclude all field names use below example:
@ToString(includeFieldNames = false)
For the same User and main class above you will get below output:
User(Soumitra, soumitra@email.com, Earth)
Call super class toString()
using below example:
@ToString(callSuper = true)
@EqualsAndHashCode
We know that there are contracts between equals()
and hashCode()
methods in Java. So this annotation @EqualsAndHashCode
is applicable on class level.
By default any field that is non-static or non-transient will be considered for inclusion into equals()
and hashCode()
methods.
Like @ToString
annotation exclude
parameter is used to prevent field being included in the generation logic. of
parameter is used to include only fields which you want in your generation logic.
There is also a callSuper
parameter for this annotation. Setting it to true will cause equals()
to verify equality by calling the equals()
from the superclass before considering fields in the current class. For the hashCode()
method, it results in the incorporation of the results of the superclass’s hashCode()
in the calculation of the hash.
Parent Class:
package com.roytuts.java.lombok.example.model;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@EqualsAndHashCode(exclude = "address")
public class User {
private String name;
private String email;
private String address;
}
Child Class:
package com.roytuts.java.lombok.example.model;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Employee extends User {
private int id;
}
Testing:
package com.roytuts.java.lombok.example;
import com.roytuts.java.lombok.example.model.Employee;
public class JavaLombokTest {
public static void main(String[] args) {
Employee employee = new Employee();
employee.setId(1234);
System.out.println(employee);
System.out.println(employee.hashCode());
employee.setName("Soumitra");
employee.setEmail("soumitra@email.com");
employee.setAddress("Earth");
System.out.println(employee);
System.out.println(employee.hashCode());
}
}
Running the main class will give you below output:
Employee(super=User(name=null, email=null, address=null), id=1234)
358833
Employee(super=User(name=Soumitra, email=soumitra@email.com, address=Earth), id=1234)
-1413876382
@Cleanup
The @Cleanup
annotation is used to release the allocated resources. When a local variable is annotated with @Cleanup
, any subsequent code is wrapped in a try/finally block that guarantees that the cleanup method is called at the end of the current scope.
By default @Cleanup
assumes that the cleanup method is named “close“, as with input and output streams. However, a different method name can be provided to the annotation’s value parameter.
Only methods which take no parameters are able to use this @Cleanup
annotation.
package com.roytuts.java.lombok.example;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import lombok.Cleanup;
public class LombokCleanupExample {
public static void main(String[] args) {
cleanUp();
}
public static void cleanUp() {
try {
@Cleanup
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[] { 'C', 'l', 'e', 'a', 'n', 'e', 'd', ' ', 'U', 'p' });
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Synchronized
Using the synchronized keyword on a method can result undesirable output on a multi-threaded environment. The synchronized keyword will lock on the current object (this) in the case of an instance method or on the class object for a static method. This means developer does not have option to apply lock on the same object, resulting in a deadlock. It is generally advisable to instead lock explicitly on a separate object that is dedicated solely to that purpose and not exposed in such a way as to allow unsolicited locking. Project Lombok provides the @Synchronized
annotation for that very purpose.
Annotating an instance method with @Synchronized
will prompt Lombok to generate a private locking field named $lock
on which the method will lock prior to executing. Similarly, annotating a static method in the same way will generate a private static object named $LOCK
for the static method to use in an identical fashion. A different locking object can be specified by providing a field name to the annotation’s value parameter. When a field name is provided, the developer must define the property as Lombok will not generate it.
package com.roytuts.java.lombok.example;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import lombok.Synchronized;
public class LombokSynchronizedExample {
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
public static void main(String[] args) {
LombokSynchronizedExample example = new LombokSynchronizedExample();
System.out.println(example.synchronizedFormat(new Date()));
}
@Synchronized
public String synchronizedFormat(Date date) {
return format.format(date);
}
}
Remember for java 8 onward you don’t need to synchronization for date as it already provides thread safety.
@SneakyThrows
To make error goes away @SneakyThrows
annotation is used.
Consider the below example:

From the above output it is obvious that you have to either throw exception or surround with try/catch block. Therefore if you annotate the handleFile()
method with @SneakyThrows
annotation then error will go away.
The method will look like below:
package com.roytuts.java.lombok.example;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import lombok.SneakyThrows;
public class LombokSneakyThrowsExample {
@SneakyThrows
public void handleFile(String file) {
InputStream inputStream = new FileInputStream(new File(file));
}
}
Now you see in the above class we don’t need to throw any exception or surround with try/catch block.
@NoArgsConstructor and @AllArgsConstructor
You may have requirement for adding all arguments and no argument constructors in your Java class. Then you can use these annotations on class level. The @NoArgsConstructor
will provide a constructor without any parameter and the @AllArgsConstructor
will provide a constructor will all fields as parameters.
You can specify the access level of the constructor using access
parameter. By default access level is public.
Thanks for reading.