Örnek
Şöyle yaparız
@Getter @Setter @NoArgsConstructor public class Car { private String manufacturer; private String model; private String engineType; private Integer power; }
@Getter @Setter @NoArgsConstructor public class Car { private String manufacturer; private String model; private String engineType; private Integer power; }
This is, perhaps, one of the least used Lombok annotations. This can be used on the classes that do implement the Closable interface and it will be similar to the try-with-resources block.
This annotation is used for applications relying on the java.util.logging framework. Similar to @Slf4j, it provides a static logger instance named log.
@Logpublic class LegacyService {public void legacyMethod() {log.info("Legacy method logged with @Log");}}
If we need to synchronize method calls, we can use Lombok’s annotation instead of the synchronized Java keyword for a safer implementation:
import lombok.With;
If we use immutable classes, we can annotate their fields with @With and the equivalent of a setter will be generated. The difference is that the with-er method will return a completely new instance of the object, with one of the fields updated. This annotation can be extremely useful for Java 17’s records
public record User (String firstName,String lastName,Long id,@With String email);User.withEmail ("...")
import lombok.experimental.Accessors;
@Data @Accessors(chain = true, fluent = true) public class Student { private String firstName; private String lastName; private String studentId; private Integer year; private List<Integer> marks; public Student(@NonNull String firstName) { this.firstName = firstName; this.studentId = generateStudentId(firstName); } private String generateStudentId(String firstName) { return firstName + new Random().nextInt(1_000); } } Student student = new Student("John").lastName("Doe").year(2);
import lombok.Singular;
ÖrnekWhen the @Singular annotation is placed on a collection property, Lombok creates special builder methods to individually add items to that collection, rather than adding the entire collection at once. This is particularly nice for tests as creating small collections in Java is not concise.
@Value@Builder(toBuilder = true)public class User {@NonNullUUID userId;@NonNullString email;@SingularSet<String> favoriteFoods;@NonNull@Builder.DefaultString avatar = “default.png”;}User user = User.builder().userId(UUID.random()).email(“grubhub@grubhub.com”).favoriteFood(“burritos”).favoriteFood(“dosas”).build()
import lombok.experimental.FieldDefaults;
This annotation provides a way to set default modifiers for the fields in a class. You can control the access level of fields and specify whether they should be final. This is particularly useful in Spring-based applications where you might want to establish consistent field-level access control without explicitly declaring it for each field.
When you annotate a class with @FieldDefaults, you can specify two key elements:Access Level: The visibility of the fields, such as PRIVATE, PROTECTED, PACKAGE, or PUBLIC. The default value is PRIVATE.Final: A Boolean value specifying whether the fields should be final. The default is false.
Setting makeFinal = true works well when you are creating immutable classes, but it does limit the functionality of other Lombok annotations like @Setter. In classes annotated with @Data, the makeFinal = true setting will essentially disable the generation of setter methods, because final fields cannot be modified once initialized.
import lombok.Data;import lombok.experimental.FieldDefaults; import lombok.AccessLevel; @Data @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class SecureBook { String title; String author; int pages; }
@Slf4j@RequiredArgsConstructor@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE)public class UserService {@NonNull UserDao userDao;}
The @FieldDefaults annotation adds the final and private modifiers to all of the fields.
Örnek@UtilityClass annotation which creates a private constructor that throws an exception, makes the class final, and makes all methods static.
@UtilityClass// will be made finalpublic class UtilityClass {// will be made staticprivate final int GRUBHUB = “ GRUBHUB”;// autogenerated by Lombok// private UtilityClass() {// throw new java.lang.UnsupportedOperationException("... cannot be instantiated");//}// will be made staticpublic void append(String input) {return input + GRUBHUB;}}
@Value is similar to @Data except, all fields are made private and final by default and setters are not generated. These qualities make @Value objects effectively immutable. As the fields are all final, there is not a no argument constructor. Instead Lombok uses @AllArgsConstructor to generate an all arguments constructor. This results in a fully-functioning, effectively-immutable object.
Short for final @ToString, @EqualsAndHashCode, @AllArgsConstructor, @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE), @Getter.
import lombok.NonNull;
Makes sure the value of object is not null. This is highly beneficial when dealing with data access object and saves risk NullPointerException that may go unchecked.
public record User ( @NonNull String firstName, String lastName, Long id, String email) { }
import lombok.NonNull;public class Foo {protected final String name;public Foo(@NonNull final String name) {this.name = name;}}
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.18</version><scope>provided</scope></dependency>
... Lombok is needed only at compile time. Because of that reason, the maven scope can (and should) be set to compile/provided.
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source> <!-- depending on your project --><target>1.8</target> <!-- depending on your project --><annotationProcessorPaths><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></path></annotationProcessorPaths></configuration></plugin></plugins></build>
compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.26'
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.22'
annotationProcessor 'org.projectlombok:lombok:1.18.22'
testCompileOnly 'org.projectlombok:lombok:1.18.22'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
}Val - Creates a local variable with val which will be initialized based on initialization expression. The local variable will also be made final.Var - Works exactly like Val but the local variable is not declared final.@Setter - Add setter for all variables.@Getter - Add getter for all the variables.@RequiredArgsConstructor - Generates constructor for each field.@NoArgsConstructor - Creates a non-parametrized constructor.@AllArgsConstructor - Creates a parametrized constructor containing all fields.@ToString - Creates toString method.@EqualsAndHashCode - Creates Equals and Hashcode implementation for fields in the class.@Data - It is a quick way of combining features of @ToString, @EqualsAndHashCode, @Getter, @Setter and @RequiredArgsConstructor.@Builder - Makes instantiation of class easier and provides a way to statically initialize fields in a class.
A common critique of Java is the verbosity created by throwing checked exceptions. Lombok has an annotation to remove the need for those pesky throws keywords: @SneakyThrows. As you might expect, the implementation is quite sneaky. It does not swallow or even wrap exceptions into a RuntimeException. Instead, it relies on the fact that at runtime, the JVM does not check for the consistency of checked exceptions. Only javac does this. So Lombok uses bytecode transformations to opt out of this check at compile time.
@SuppressWarnings("unchecked") static <T extends Throwable> void sneakyThrow(Throwable t) throws T { throw (T) t; } static void testSneaky() { final Exception e = new Exception(); sneakyThrow(e); // No Errors }
… Otherwise, if the bound set contains throws αi, and the proper upper bounds of αi are, at most, Exception, Throwable, and Object, then Ti = RuntimeException
This exact case applies to sneakyThrows, It states that if the type’s only upper bound is almost Exception, Throwable, and Object, then T will be inferred to be a RuntimeException as per the specification, so it compiles.
public class SneakyThrows {@SneakyThrows public void sneakyThrow() { throw new Exception(); } }
Aslında kodu şu hale getiriyor@SneakyThrowspublic static Date parseDate(String dateStr) {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");return format.parse(dateStr);}
public static Date parseDate(String dateStr) {try {SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");return format.parse(dateStr);} catch (ParseException e) {throw new RuntimeException(e);}}
@SneakyThrows(IOException.class) void throwException(String a) { ... throw new IOException(); }
import lombok.Builder;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String firstName;
private String lastName;
private String birthdate;
}
Şöyle kullanabiliriz.public Customer mapFieldSet(FieldSet fieldSet) throws BindException {
return Customer.builder()
.id(fieldSet.readLong("id"))
.firstName(fieldSet.readRawString("firstName"))
.lastName(fieldSet.readRawString("lastName"))
.birthdate(fieldSet.readRawString("birthdate"))
.build();
}@Builder@AllArgsConstructor(access = AccessLevel.PRIVATE)public class WebClientComposer {static final boolean DEFAULT_SOCKET_KEEP_ALIVE_ENABLED = true;static final boolean DEFAULT_HTTP_PROXY_ENABLED = false;static final int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 5000;static final int MAX_IN_MEMORY_SIZE_BYTES = 1024 * 1024;@Builder.Defaultprivate final String baseUrl = "";@Builder.Defaultprivate final int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT_MILLIS;@Builder.Defaultprivate final int readTimeoutSecs = 0;@Builder.Defaultprivate final boolean socketKeepAlive = DEFAULT_SOCKET_KEEP_ALIVE_ENABLED;@Builder.Defaultprivate final int maxInMemorySize = MAX_IN_MEMORY_SIZE_BYTES;@Builder.Defaultprivate final int maxPoolConnectionSize = ...;...}
@Data @Builder(builderMethodName = "internalBuilder") static class Student { @NonNull private String firstName; private String lastName; private String studentId; private Integer year; private List<Integer> marks; public static StudentBuilder builder(String name) { return internalBuilder().firstName(name); } }
@Data public class Student { @NonNull private String firstName; private String lastName; private String studentId; private Integer year; private List<Integer> marks; public static StudentBuilder builder(String name) { return internalBuilder().firstName(name); } @Builder(builderMethodName = "internalBuilder") private Student(String firstName, String lastName, List<Integer> marks, Integer year) { this.firstName = firstName; this.lastName = lastName; this.marks = marks; this.year = year; //generate some value based on other fields this.studentId = generateStudentId(firstName); } private String generateStudentId(String firstName) { return firstName + new Random().nextInt(1000); } }
@Data @Accessors(chain = true, fluent = true) public class Student { private String firstName; private String lastName; private String studentId; private Integer year; private List<Integer> marks; public Student(@NonNull String firstName) { this.firstName = firstName; this.studentId = generateStudentId(firstName); } private String generateStudentId(String firstName) { return firstName + new Random().nextInt(1000); } } Student student = new Student("John").lastName("Doe").year(2);
@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder") method(String a, String b, String c) { ... acutal logic here ... } private class MethodBuilder { private String a = "Hello"; private String b = "builder"; private String c = "world!"; }
@Builder(builderMethodName = "methodBuilder", buildMethodName = "call") void method(@NotNull String firstParam, @NotNull String secondParam, String thirdParam, String fourthParam, Long fifthParam, @NotNull Object sixthParam) { ... } methodBuilder() .firstParam("A") .secondParam("B") .sixthParam(new Object()) .call(); methodBuilder() .firstParam("A") .secondParam("B") .thirdParam("C") .fifthParam(2L) .sixthParam("D") .call(); methodBuilder() .firstParam("A") .secondParam("B") .fifthParam(3L) .sixthParam(this) .call();
@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder") public <T extends Collection> T read(final byte[] content, final Class<T> type) {...} public <T extends Collection> MethodBuilder<T> methodBuilder(final Class<T> type) { return new MethodBuilder<T>().type(type); } public class MethodBuilder<T extends Collection> { private Class<T> type; public MethodBuilder<T> type(Class<T> type) { this.type = type; return this; } public T call() { return read(content, type); } }
@Builder(builderMethodName = "methodBuilder", buildMethodName = "call", builderClassName = "MethodBuilder") public <T extends Collection> T read(final byte[] content, final Class<T> type) {...} public class MethodBuilder<T extends Collection> { private Class<T> type; public <L extends Collection> MethodBuilder<L> type(final Class<L> type) { this.type = (Class)type; return (MethodBuilder<L>) this; } public T call() { return read(content, type); } }
Finally, the toBuilder = true setting adds an instance method toBuilder() that creates a builder object populated with all the values of that instance. This enables an easy way to create a new instance prepopulated with all the values from the original instance and change just the fields needed. This is particularly useful for @Value classes because the fields are immutable.
@Builder(toBuilder=true)
class Foo {
int x;
...
}
Foo f0 = Foo.builder().build();
Foo f1 = f0.toBuilder().x(42).build();import lombok.RequiredArgsConstructor;The @RequiredArgsConstructor annotation in Java Lombok is used to automatically generate a constructor for a class that initializes all final fields, as well as any non-final fields with the @NonNull annotation.
@RequiredArgsConstructor
public class Fooo {
...
}
Örnek
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public class HelloResponseDto {
private final String name;
private final int amount;
}