Project Lombok

Project Lombok jest biblioteką Javy, która w znaczącym stopniu ułatwia definiowanie klas, szczególnie klas modelu, które powinny być zgodne ze standardem JavaBeans lub być klasami dla obiektów niemodyfikowalnych (immutable).

Omówienie

Jest to projekt bardzo niewielkich rozmiarów, który po wejściu na oficjalną stronę może nas nieco odstraszać layoutem z lat 90tych:

lombok layout strony

Okazuje się jednak, że pierwsze wrażenie jest w tym przypadku czymś, czym zdecydowanie nie powinniśmy się kierować, ponieważ Lombok w znacznym stopniu może nam ułatwić życie i zaoszczędzić setki, czy tysiące linii kodu. Każdy kto od jakiegoś czasu pisze w Javie zdaje sobie sprawę z uciążliwości tworzenia klas, w których pola oznaczamy jako prywatne, generujemy dla nich gettery i settery, następnie stwierdzamy, że przydałby nam się także konstruktor pozwalający przekazać od razu wszystkie niezbędne pola podczas tworzenia obiektu. W celu porównywania obiektów niezbędna będzie także metoda equals() , ale ponieważ powinna ona spełniać pewien kontrakt to jednocześnie powinniśmy wygenerować także hashCode() . Żeby uprzyjemnić sobie wyświetlanie takich obiektów na pewno przyda się nam także metoda ***toString()***.

Spójrzmy na klasyczną klasę Person, która po prostu przechowuje imię i nazwisko:

public class Person {
     private String firstName;
     private String lastName;
     
     public Person(String firstName, String lastName) {
         super();
         this.firstName = firstName;
         this.lastName = lastName;
     }
     
     public String getFirstName() {
         return firstName;
     }
     public void setFirstName(String firstName) {
         this.firstName = firstName;
     }
     public String getLastName() {
         return lastName;
     }
     public void setLastName(String lastName) {
         this.lastName = lastName;
     }
 
     @Override
     public String toString() {
         return "Person [firstName=" + firstName + ", lastName=" + lastName + "]";
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
         result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
         return result;
     }
 
     @Override
     public boolean equals(Object obj) {
         if (this == obj)
             return true;
         if (obj == null)
             return false;
         if (getClass() != obj.getClass())
             return false;
         Person other = (Person) obj;
         if (firstName == null) {
             if (other.firstName != null)
                 return false;
         } else if (!firstName.equals(other.firstName))
             return false;
         if (lastName == null) {
             if (other.lastName != null)
                 return false;
         } else if (!lastName.equals(other.lastName))
             return false;
         return true;
     }
 }

65 linii kodu z czego w rzeczywistości ręcznie zapisujemy tylko trzy pierwsze. Jeżeli ktoś nie jest zupełnym masochistą, to całą resztę wygeneruje z pomocą swojego ulubionego IDE.

Weźmy pod uwagę, że w klasie tej mamy tylko dwa pola, problem rośnie coraz bardziej wraz z dodawaniem każdego kolejnego. Na ratunek przychodzi nam jednak Lombok...

Instalacja

Lomboka możemy wykorzystywać na kilka sposobów. Jest to narzędzie, z którego możemy skorzystać po prostu z linii poleceń podczas kompilowania naszych klas, dużo wygodniej jest go jednak wpiąć do swojego IDE, np. Eclipse. W tym celu pobieramy bibliotekę z oficjalnej strony i uruchamiamy plik przy pomocy polecenia:

java -jar lombok.jar

Na ekranie pojawi się nam okno, w którym możemy wskazać lokalizację, w której jest zainstalowany / wypakowany eclipse.

lombok instalacja

Klikamy Install/Update i wychodzimy z instalatora. Jeśli mieliśmy uruchomione IDE to należy je teraz zrestartować. Jeśli pominiemy ten krok, to Lombok nie będzie działał automatycznie w tle.

Drugim krokiem jest stworzenie projektu i dodanie Lomboka jako bibliotekę do projektu. W eclipse najlepiej stworzyć w swoim projekcie folder o nazwie np. lib, umieścić w nim plik lombok.jar, a następnie dodać go do projektu klikając prawym przyciskiem myszy i wybierając Build Path > Add to Build Path.

dodanie biblioteki

Adnotacje

Lombok wykorzystuje podejście convention over configuration, co oznacza, że przy pomocy adnotacji możemy wskazać, co chcielibyśmy wygenerować w naszej klasie. Lombok zajmie za nas tym co normalnie "wyklikujemy" w naszym IDE.

Wracając do naszego poprzedniego przykładu zobaczmy jak może wyglądać uproszczona klasa:

import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
 
 @AllArgsConstructor(access=AccessLevel.PUBLIC)
 @ToString
 @EqualsAndHashCode
 public class Person {
     @Getter(value = AccessLevel.PUBLIC)
     @Setter(value = AccessLevel.PUBLIC)
     private String firstName;
     @Getter(value = AccessLevel.PUBLIC)
     @Setter(value = AccessLevel.PUBLIC)
     private String lastName;
 }

Jak widać do dyspozycji mamy adnotacje, których nazwa mówi wszystko.

  • @AllArgsConstructor wygeneruje nam konstruktor ustawiający wszystkie pola
  • @ToString i @EqualsAndHashCode wygenerują odpowiednie metody nadpisując domyślne z klasy Object
  • @Getter i @Setter dodane przy odpowiednich polach wygenerują dla nas gettery i settery.

Jak widać możemy również m.in. określić jakie specyfikatory dostępu mają mieć poszczególne metody, jednak ponieważ dostęp publiczny jest w Lomboku domyślny, to możemy pójść jeszcze o krok dalej.

import lombok.AllArgsConstructor;
 import lombok.Data;
 
 @Data
 @AllArgsConstructor
 public class Person {
     private String firstName;
     private String lastName;
 }

Adnotacja @Data generuje settery, gettery, oraz metody z klasy Object. Jeżeli nasza klasa miałaby reprezentować obiekty niemodyfikowalne, czyli pola firstName i lastName oznaczylibyśmy dodatkowo jako final, to nie byłaby potrzebna adnotacja @AllArgsConstructor.

Jeżeli w swoich metodach chcesz wymusić to, żeby pola nie mogły być nullami, to zamiast definiowania ifów przychodzi kolejne wybawienie w postaci adnotacji @NonNull . W przypadku obiektów reprezentujących zasoby, na których należy pamiętać o wywołaniu metody close możemy posłużyć się adnotacją @Cleanup (chyba, że korzystamy z konstrukcji try-with-resources z Javy 7 wtedy nie ma takiej konieczności).

Jak widać Lombok może nam zaoszczędzić masę czasu. Jest to rzecz niesamowicie prosta, ale niesamowicie użyteczna. Każda z przedstawionych powyżej adnotacji posiada dodatkowo możliwość konfiguracji poprzez opcjonalne atrybuty, a to i tak nie wszystkie adnotacje, które Lombok nam udostępnia. Zachęcam do zajrzenia do dokumentacji, która jest bogata w proste przykłady idealnie obrazujące zastosowanie każdej z nich.

Dyskusja i komentarze

Masz pytania do tego wpisu? Może chcesz się podzielić spostrzeżeniami? Zapraszamy dyskusji na naszej grupie na Facebooku.