Project Lombok is a Java library that automatically plugs into projects and generates common boilerplate code like getters, setters, equals, hashCode and toString methods through annotations. This reduces code verbosity and speeds up development. The document discusses how to add Lombok dependencies to Maven and Gradle projects, and demonstrates how annotations like @Getter, @Setter, @ToString, @EqualsAndHashCode, @NoArgsConstructor and @Builder can be used to generate these common methods automatically. Potential downsides are that Lombok relies on non-public APIs so compiler upgrades could break code, and it cannot detect constructors of superclasses.
W jaki sposób dodac Lomboka do projektu? Wystarczy dodać dependency do pom.xml i już, cała magia jest zrobiona, maven ściągnie odpowiedniego jara i można spokojnie używać w projekcie.
Gdy projekt jest budowany przy użyciu Gradle, również można dodać do niego Lomboka. W zależności od wersji:
Gradle 2.12 lub nowszy -> w pliku build.gradle w sekcji dependencies umieszczamy: compileOnly
Gradle starszy -> w pliku build.gradle w sekcji dependencies umieszczamy: provided
Annotation processing to narzęcie wbudowane w kompilator javy do skanowania i przetwarzania adnotacji podczas kompilacji. Można zarejestrować własny procesor adnotacji dla konkretnych adnotacji
Procesor adnotacji dla konkretnych adnotacji bierze kod javy (lub byte code) i na jego podstawie generuje pliki (zazwyczaj *.java). Co to znaczy? Pozwala to generować kod. Wygenerowany kod jest w wygenerowanym pliku *.java. Oznacza to, że nie można zmieniać istniejącej klasy poprzez dodanie metody. Wygenerowany plik java będzie skompilowany przez kompilator (javac) jak każdy inny plik napisany ręcznie.
Annotation processing is a tool build in javac for scanning and processing annotations at compile time. You can register your own annotation processor for certain annotations.
An annotation processor for a certain annotation takes java code (or compiled byte code) as input and generate files (usually .java files) as output. What does that exactly means? You can generate java code! The generated java code is in a generated .java file. So you can not manipulate an existing java class for instance adding a method. The generated java file will be compiled by javac as any other hand written java source file.
Adnotacje Getter i Setter służą do generowanie getterów i seterów, czyli to, gdzie możemy zaoszczędzić szczególnie dużo kodu. Adnotacje mogą być dodane na poziomie klasy, wtedy metody są generowane dla wszystkich pól, albo można wygenerować te metody tylko dla konkretnych pól.
Adnotacje Getter i Setter służą do generowanie getterów i seterów, czyli to, gdzie możemy zaoszczędzić szczególnie dużo kodu. Adnotacje mogą być dodane na poziomie klasy, wtedy metody są generowane dla wszystkich pól, albo można wygenerować te metody tylko dla konkretnych pól.
Adnotacje Getter i Setter służą do generowanie getterów i seterów, czyli to, gdzie możemy zaoszczędzić szczególnie dużo kodu. Adnotacje mogą być dodane na poziomie klasy, wtedy metody są generowane dla wszystkich pól, albo można wygenerować te metody tylko dla konkretnych pól.
Generuje metody equals() i hashCode().
Generuje metody equals() i hashCode().
Generuje metody equals() i hashCode().
Generuje metody equals() i hashCode().
Generuje metody equals() i hashCode().
Proste generacja metody toString().
Proste generacja metody toString().
Podstawowa adnotacja dodająca kod konstruktora bezargumentowego to NoArgsConstructor.
Adnotacja NoArgsConstructor jest dodawana na poziomie deklaracji klasy.
Adnotacja AllArgsConstructor generuje konstruktor z wszystkimi argumentami.
Adnotacja AllArgsConstructor generuje konstruktor z wszystkimi argumentami.
RequiredArgsConstructor – tworzy konstruktor z polami, które są wymagane – pola oznaczone jako final lub pola z adnotacja @NonNull.
Można łączyć wiele adnotacji, więc wygenerować tylko jeden z kontstruktorów, wszystkie trzy lub dowolną ich kombinację, w zależności od naszych potrzeb. Oczywiście, można również dopisać inne, bardziej specyficzne konstruktory.
RequiredArgsConstructor – tworzy konstruktor z polami, które są wymagane – pola oznaczone jako final lub pola z adnotacja @NonNull.
Można łączyć wiele adnotacji, więc wygenerować tylko jeden z kontstruktorów, wszystkie trzy lub dowolną ich kombinację, w zależności od naszych potrzeb. Oczywiście, można również dopisać inne, bardziej specyficzne konstruktory.
Adnotacja @Data generuje konstruktor bezargumentowy, gettery/setery wszystkich pól, metody equals, hashCode, toString.
Połączenie wielu adnotacji w jednej klasie. Jak widać, Gettery dla wszystkich pól, Settery tylko dla dwóch pól – firstName, lastName. Do tego metody equals(), hashCode() i toString(). Konstruktory nie zostały wygenerowane, jedynie konstruktor napisany z palca.
Pokazać jaka róznica w szybkości napisania klasy bez lomboka i z lombokiem.
A method annotated with @Builder (from now on called the target) causes the following 7 things to be generated:
- An inner static class named SuperheroBuilder, with the same type arguments as the static method (called the builder).
In the builder: One private non-static non-final field for each parameter of the target.
In the builder: A package private no-args empty constructor.
In the builder: A 'setter'-like method for each parameter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
In the builder: A build() method which calls the method, passing in each field. It returns the same type that the target returns.
In the builder: A sensible toString() implementation.
In the class containing the target: A builder() method, which creates a new instance of the builder.
A method annotated with @Builder (from now on called the target) causes the following 7 things to be generated:
- An inner static class named SuperheroBuilder, with the same type arguments as the static method (called the builder).
In the builder: One private non-static non-final field for each parameter of the target.
In the builder: A package private no-args empty constructor.
In the builder: A 'setter'-like method for each parameter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
In the builder: A build() method which calls the method, passing in each field. It returns the same type that the target returns.
In the builder: A sensible toString() implementation.
In the class containing the target: A builder() method, which creates a new instance of the builder.
A method annotated with @Builder (from now on called the target) causes the following 7 things to be generated:
- An inner static class named SuperheroBuilder, with the same type arguments as the static method (called the builder).
In the builder: One private non-static non-final field for each parameter of the target.
In the builder: A package private no-args empty constructor.
In the builder: A 'setter'-like method for each parameter of the target: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
In the builder: A build() method which calls the method, passing in each field. It returns the same type that the target returns.
In the builder: A sensible toString() implementation.
In the class containing the target: A builder() method, which creates a new instance of the builder.
Dlaczego używać projektu Lombok w projekcie?
Trzy rzeczy.
Mniej kodu. I to kodu, który musimy napisać i zajmuje dużo czasu, nawet jeśli używamy IDE do wygenerowania go, zajmuje to czas, który możemy spożytkować lepiej i bardziej produktywnie.
Kod klasy jest czytelniejszy, co wynika z punktu pierwszego. Jak wiadomo, większość czasu poświęcamy na czytanie kodu, nie na pisanie, a zredukowanie liczby linii kodu ułatwia zapoznanie się z klasą.
Szybsze programowanie. Dużo szybciej jest dodać adnotacje zamiast pisania ciała metody.
POL
1. Niezdolność do wykrycia konstruktora klasy bazowej. To znaczy, jeżeli klasa bazowa nie posiada defaultowego konstruktora, żadna klasa dziedzicząca ni emoże użyć adnotacji @Data bez bezpośredniego napisania konstruktora, który użyje dostępnego konstruktora klasy bazowej.
2. Lombok jest ściśle powiązany z kompilatorem Javy. Ponieważ API procesora adnotacji pozwala jedynie na tworzenie nowych plików podczas kompilacji (nie modyfikację istniejących) lombok używa API jako punktu wejściowego (entry point) żeby zmodyfikować kompilator javy. Powoduje to, że użyte jest niepubliczne API. Użycie Lomboka może sprawić, że przy upgradzie kompilatora nasz kod przestanie działać.
ENG
1. One important problem is the inability to detect the constructors of a superclass. This means that if a superclass has no default constructor any subclasses cannot use the @Data annotation without explicitly writing a constructor to make use of the available superclass constructor. .
2. A limitation of Lombok is the fact that it is closely tied to the java compiler. Since the annotation processor API only allows creation of new files during the compilation (and not the modification of the existing files) lombok uses that API as a entry point to modify the java compiler. Unfortunately these modifications of the compiler make heavy usage of non-public APIs. Using lombok may be a good idea but you must be aware that upgrading your compiler may broke your code.