Never write another getter or equals method again using Project Lombok. Early access to future java features such as val
and much more.
Project Lombok is a java library that automatically plugs into your editor and builds tools, spicing up your java.
Check this amazing Project Lombok demo
Features of Project Lombok
Installation of Project Lombok is given at last of this post. So firstly check top 10 features of Lombok.
val
Finally! Hassle-free final local variables.
You can use val
as the type of a local variable declaration instead of actually writing the type. When you do this, the type will be inferred from the initializer expression. The local variable will also be made final. This feature works on local variables and on foreach loops only, not on fields. The initializer expression is required.
val
is actually a ‘type’ of sorts, and exists as a real class in the lombok
package. You must import it for val to work (or use lombok.val
as the type). The existence of this type on a local variable declaration triggers both the adding of the final
keyword as well as copying the type of the initializing expression which overwrites the ‘fake’ val
type.
Example of val:
import java.util.ArrayList; import java.util.HashMap; import lombok.val; public class ValExample { public String example() { val example = new ArrayList<String>(); example.add("Hello, World!"); val foo = example.get(0); return foo.toLowerCase(); } public void example2() { val map = new HashMap<Integer, String>(); map.put(0, "zero"); map.put(5, "five"); for (val entry : map.entrySet()) { System.out.printf("%d: %s\n", entry.getKey(), entry.getValue()); } } }
WARNING: This feature does not currently work in NetBeans.
var
Mutable! Hassle-free local variables.
var
works exactly like val
, except the local variable is not marked as final
.
The type is still entirely derived from the mandatory initializer expression, and any further assignments, while now legal (because the variable is no longer final
), aren’t looked at to determine the appropriate type.
[tmh_article_ads]
For example, var x = "Hello"; x = Color.RED;
does not work; the type of x will be inferred to be java.lang.String
and thus, the x = Color.RED
assignment will fail. If the type of x
was inferred to be java.lang.Object
this code would have compiled, but that’s not howvar
works.
@NonNull
How I learned to stop worrying and love the NullPointerException.
You can use @NonNull
on the parameter of a method or constructor to have lombok generate a null-check statement for you.
Lombok has always treated any annotation named @NonNull
on a field as a signal to generate a null-check if lombok generates an entire method or constructor for you, via for example @Data
. Now, however, using lombok’s own @lombok.NonNull
on a parameter results in the insertion of just the null-check statement inside your own method or constructor.
The null-check looks like if (param == null) throw new NullPointerException("param is marked @NonNull but is null");
and will be inserted at the very top of your method. For constructors, the null-check will be inserted immediately following any explicit this()
or super()
calls.
If a null-check is already present at the top, no additional null-check will be generated.
Example of @NonNull:
import lombok.NonNull; public class NonNullExample extends Something { private String name; public NonNullExample(@NonNull Person person) { super("Hello"); this.name = person.getName(); } }
@Cleanup
Automatic resource management: Call your close()
methods safely with no hassle.
You can use @Cleanup
to ensure a given resource is automatically cleaned up before the code execution path exits your current scope. You do this by annotating any local variable declaration with the @Cleanup
annotation like so:
@Cleanup InputStream in = new FileInputStream("some/file");
As a result, at the end of the scope you’re in, in.close()
is called. This call is guaranteed to run by way of a try/finally construct. Look at the example below to see how this works.
If the type of object you’d like to cleanup does not have a close()
method, but some other no-argument method, you can specify the name of this method like so:
@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);
By default, the cleanup method is presumed to be close()
. A cleanup method that takes 1 or more arguments cannot be called via @Cleanup
.
Example of @Cleanup
import lombok.Cleanup; import java.io.*; public class CleanupExample { public static void main(String[] args) throws IOException { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup OutputStream out = new FileOutputStream(args[1]); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } }
@Getter and @Setter
Never write againpublic int getFoo() {return foo;}
.
You can annotate any field with @Getter
and/or @Setter
, to let lombok generate the default getter/setter automatically.
A default getter simply returns the field, and is named getFoo
if the field is called foo
(or isFoo
if the field’s type is boolean
). A default setter is named setFoo
if the field is called foo
, returns void
, and takes 1 parameter of the same type as the field. It simply sets the field to this value.
The generated getter/setter method will be public
unless you explicitly specify an AccessLevel
, as shown in the example below. Legal access levels are PUBLIC
, PROTECTED
, PACKAGE
, and PRIVATE
.
You can also put a @Getter
and/or @Setter
annotation on a class. In that case, it’s as if you annotate all the non-static fields in that class with the annotation.
You can always manually disable getter/setter generation for any field by using the special AccessLevel.NONE
access level. This lets you override the behaviour of a @Getter
, @Setter
or @Data
annotation on a class.
Example of @Getter/@Setter
import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class GetterSetterExample { /** * Age of the person. Water is wet. * * @param age New value for this person's age. Sky is blue. * @return The current value of this person's age. Circles are round. */ @Getter @Setter private int age = 10; /** * Name of the person. * -- SETTER -- * Changes the name of this person. * * @param name The new value. */ @Setter(AccessLevel.PROTECTED) private String name; @Override public String toString() { return String.format("%s (age: %d)", name, age); } }
@ToString
No need to start a debugger to see your fields: Just let project lombok generate a toString
for you!
Any class definition may be annotated with @ToString
to let project lombok generate an implementation of the toString()
method. By default, it’ll print your class name, along with each field, in order, separated by commas.
By setting the includeFieldNames
parameter to true you can add some clarity (but also quite some length) to the output of the toString()
method.
Example of @toString
import lombok.ToString; @ToString public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private Shape shape = new Square(5, 10); private String[] tags; @ToString.Exclude private int id; public String getName() { return this.name; } @ToString(callSuper=true, includeFieldNames=true) public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } } }
@EqualsAndHashCode
Generates hashCode
and equals
implementations from the fields of your object.
Any class definition may be annotated with @EqualsAndHashCode
to let lombok generate implementations of the equals(Object other)
and hashCode()
methods. By default, it’ll use all non-static, non-transient fields, but you can modify which fields are used (and even specify that the output of various methods is to be used) by marking type members with @EqualsAndHashCode.Include
or @EqualsAndHashCode.Exclude
. Alternatively, you can specify exactly which fields or methods you wish to be used by marking them with @EqualsAndHashCode.Include
and using @EqualsAndHashCode(onlyExplicitlyIncluded = true)
.
[tmh_article_ads]
If applying @EqualsAndHashCode
to a class that extends another, this feature gets a bit trickier. Normally, auto-generating an equals
and hashCode
method for such classes is a bad idea, as the superclass also defines fields, which also need equals/hashCode code but this code will not be generated.
Example of @EqualAndHashCode
import lombok.EqualsAndHashCode; @EqualsAndHashCode public class EqualsAndHashCodeExample { private transient int transientVar = 10; private String name; private double score; @EqualsAndHashCode.Exclude private Shape shape = new Square(5, 10); private String[] tags; @EqualsAndHashCode.Exclude private int id; public String getName() { return this.name; } @EqualsAndHashCode(callSuper=true) public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } } }
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor
Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.
This set of 3 annotations generate a constructor that will accept 1 parameter for certain fields, and simply assigns this parameter to the field.
@NoArgsConstructor
will generate a constructor with no parameters. If this is not possible (because of final fields), a compiler error will result instead, unless @NoArgsConstructor(force = true)
is used, then all final fields are initialized with 0
/ false
/ null
. For fields with constraints, such as @NonNull
fields, no check is generated,so be aware that these constraints will generally not be fulfilled until those fields are properly initialized later. Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor. This annotation is useful primarily in combination with either @Data
or one of the other constructor generating annotations.
@RequiredArgsConstructor
generates a constructor with 1 parameter for each field that requires special handling. All non-initialized final
fields get a parameter, as well as any fields that are marked as @NonNull
that aren’t initialized where they are declared. For those fields marked with @NonNull
, an explicit null check is also generated. The constructor will throw a NullPointerException
if any of the parameters intended for the fields marked with @NonNull
contain null
. The order of the parameters match the order in which the fields appear in your class.
@AllArgsConstructor
generates a constructor with 1 parameter for each field in your class. Fields marked with @NonNull
result in null checks on those parameters.
Example of @ArgConstructor
import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import lombok.AllArgsConstructor; import lombok.NonNull; @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<T> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; } }
@Data
All together now: A shortcut for @ToString
, @EqualsAndHashCode
, @Getter
on all fields, @Setter
on all non-final fields, and @RequiredArgsConstructor
!
@Data
is a convenient shortcut annotation that bundles the features of @ToString
, @EqualsAndHashCode
, @Getter
/ @Setter
and @RequiredArgsConstructor
together: In other words, @Data
generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate toString
, equals
and hashCode
implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with @NonNull
, in order to ensure the field is never null.
@Data
is like having implicit @Getter
, @Setter
, @ToString
, @EqualsAndHashCode
and @RequiredArgsConstructor
annotations on the class (except that no constructor will be generated if any explicitly written constructors already exist). However, the parameters of these annotations (such as callSuper
, includeFieldNames
and exclude
) cannot be set with @Data
. If you need to set non-default values for any of these parameters, just add those annotations explicitly; @Data
is smart enough to defer to those annotations.
Example of @Data
import lombok.AccessLevel; import lombok.Setter; import lombok.Data; import lombok.ToString; @Data public class DataExample { private final String name; @Setter(AccessLevel.PACKAGE) private int age; private double score; private String[] tags; @ToString(includeFieldNames=true) @Data(staticConstructor="of") public static class Exercise<T> { private final String name; private final T value; } }
@Synchronized
synchronized
done right: Don’t expose your locks.
@Synchronized
is a safer variant of the synchronized
method modifier. Like synchronized
, the annotation can be used on static and instance methods only. It operates similarly to the synchronized
keyword, but it locks on different objects. The keyword locks on this
, but the annotation locks on a field named $lock
, which is private.
If the field does not exist, it is created for you. If you annotate a static
method, the annotation locks on a static field named $LOCK
instead.
If you want, you can create these locks yourself. The $lock
and $LOCK
fields will of course not be generated if you already created them yourself. You can also choose to lock on another field, by specifying it as a parameter to the @Synchronized
annotation. In this usage variant, the fields will not be created automatically, and you must explicitly create them yourself, or an error will be emitted.
Example of @Synchronised
import lombok.Synchronized; public class SynchronizedExample { private final Object readLock = new Object(); @Synchronized public static void hello() { System.out.println("world"); } @Synchronized public int answerToLife() { return 42; } @Synchronized("readLock") public void foo() { System.out.println("bar"); } }
The list is not ending here and if you like this article and want to know more feature of Project Lombok then comment us below 🙂
Share your thoughts