Wspólna funkcjonalność obiektów Java z Project Lombok

Projekt Lombok to mała biblioteka, której można użyć w celu zmniejszenia ilości standardowego kodu Java, który jest zwykle pisany dla klas Java. Projekt Lombok robi to za pomocą adnotacji, które można dodać do klasy Java, dla której pożądane są wspólne metody. Większość adnotacji ma samoopis w swoich nazwach: @Getter, @Setter, @EqualsAndHashCode, @ToString i @NoArgsConstructor to przykłady. W tym poście pokazuję, jak zastosować proste adnotacje Lombok, aby dodać te powszechnie pisane metody do klasy Java.

Oto prosta klasa bez wstępnie zdefiniowanej nadpisanej wersji metody toString ().

toString-less Person.java

package dustin.examples; /** * Simple Person class without boilerplate. * * @author Dustin */ public class Person { private String lastName; private String firstName; } 

Po wygenerowaniu powyższej klasy i wywołaniu jej niejawnie dziedziczonej (z Object) metody toString (), dane wyjściowe wyglądają tak, jak pokazano na następnym obrazku.

Moglibyśmy napisać jawną metodę toString () lub użyć Project Lombok. Następny fragment kodu demonstruje podejście Project Lombok.

Person.java z adnotacją Lombok @ToString

package dustin.examples; import lombok.ToString; /** * Simple Person class without boilerplate. * * @author Dustin */ @ToString public class Person { private String lastName; private String firstName; } 

Wyniki drukowania zawartości tej klasy za pomocą metody toString () dostarczonej przez Lombok są pokazane poniżej.

Obecnie istnieje lepsza reprezentacja metody toString () obiektu Person, ale jego pola nadal nie są zainicjalizowane, więc widzimy tylko wartości null. Możemy ponownie użyć Lomboka do stworzenia konstruktora.

Person.java z adnotacją @AllArgsConstructor firmy Lombok

package dustin.examples; import lombok.AllArgsConstructor; import lombok.ToString; /** * Simple Person class without boilerplate. * * @author Dustin */ @ToString @AllArgsConstructor public class Person { private String lastName; private String firstName; } 

Teraz mogę (właściwie muszę) przekazać parametry podczas tworzenia instancji obiektu Person. Wyniki są pokazane na następnym obrazie ekranu. W tym przypadku mój kod klienta (Main.java) wyświetla błąd kompilacji w NetBeans, ponieważ NetBeans nie wierzy, że w Person istnieje konstruktor akceptujący dwa ciągi. Pomimo czerwonych falistych znaków, kod buduje się, gdy poproszę NetBeans o jego zbudowanie.

Klasa taka jak Person.java jest często klasą danych, która będzie musiała być używana do porównań i prawdopodobnie kluczy kolekcji opartych na hashCode. Ważne jest, aby poprawnie utworzyć implementacje equals (Object) i hashCode () oraz upewnić się, że są tworzone razem. Ponieważ istnieją domyślne metody equals i hashCode dostarczane przez nadrzędną klasę Object, kod Java wykorzystujący instancje Person będzie mógł wykonywać equals i / lub hashCode, ale prawdopodobnie nie będą one tym, czego naprawdę chcemy. Kiedy główna klasa wykonywalna jest zmieniana na następną listę kodu, widzimy dane wyjściowe po tym, które mówi nam, że porównanie równości jest wykonywane całkowicie na podstawie tożsamości, a nie zawartości.

Main.java That Tests równa się () Implementacja

package dustin.examples; import static java.lang.System.out; /** * Simple Main for uses Project Lombok-powered classes. * * @author Dustin */ public class Main { public static void main(final String[] arguments) { //final Person person = new Person(); final Person person = new Person("Miles", "Linda"); out.println(person); final String sameLastName = "Smith"; final String sameFirstName = "Sam"; final Person person1 = new Person(sameLastName, sameFirstName); final Person person2 = new Person(sameLastName, sameFirstName); if (person1.equals(person2)) { out.println("Same person!"); } else { out.println("Different people!"); } } } 

To prawie nigdy nie jest tym, czego tutaj chcemy. Zamiast tego wymagana jest jawna implementacja równości. Podoba mi się fakt, że adnotacja Lombok w tym miejscu, @EqualsAndHashCode, generuje tylko oba te elementy razem, ponieważ nie ma sensu jawne zastępowanie ich indywidualnie. Lista klas Person.java jest wyświetlana jako następna po dodaniu adnotacji @EqualsAndHashCode.

Person.java z @EqualsAndHashCode

package dustin.examples; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Simple Person class without boilerplate. * * @author Dustin */ @ToString @AllArgsConstructor @EqualsAndHashCode public class Person { private String lastName; private String firstName; } 

Wyjście jest teraz lepsze.

Nadal nie mam dobrego sposobu, aby uzyskać dostęp do każdego pola publicznego osobno, jeśli jest to konieczne. Na przykład, jeśli chciałbym zrobić coś w swoim kodzie na podstawie nazwiska, nie mam dobrego sposobu, aby to osiągnąć bez podejmowania drastycznych kroków. Mogę tu znowu użyć Lombok.

W tym przykładzie załóżmy, że przyjęliśmy błędne założenie, że może się zmienić tylko nazwisko osoby. Ze względu na to założenie udostępnimy tylko adnotację Lombok @Setter dla nazwiska, ale z adnotacją @Getter dla obu pól. Zmieniony kod osoby jest wyświetlany jako następny.

Person.java z @Getter i @Setter

package dustin.examples; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; /** * Simple Person class without boilerplate. * * @author Dustin */ @ToString @AllArgsConstructor @EqualsAndHashCode public class Person { @Getter @Setter private String lastName; @Getter private String firstName; } 

Oto zaktualizowana klasa Main do uruchomienia tego przykładu:

Main.java, który korzysta z New Setter / Getter

package dustin.examples; import static java.lang.System.out; /** * Simple Main for uses Project Lombok-powered classes. * * @author Dustin */ public class Main { public static void main(final String[] arguments) { //final Person person = new Person(); final Person person = new Person("Miles", "Linda"); out.println(person); final String sameLastName = "Smith"; final String sameFirstName = "Sam"; final Person person1 = new Person(sameLastName, sameFirstName); final Person person2 = new Person(sameLastName, sameFirstName); if (person1.equals(person2)) { out.println("Same person!"); } else { out.println("Different people!"); } final Person accessiblePerson = new Person("Garzminski", "Gary"); out.println("The last name is " + accessiblePerson.getLastName()); out.println("The first name is " + accessiblePerson.getFirstName()); //accessiblePerson.setFirstName("Grady"); accessiblePerson.setLastName("Garfunkel"); out.println("The new last name is " + accessiblePerson.getLastName()); } } 

Musiałem skomentować wywołanie, aby ustawić imię osoby, aby kod mógł się zbudować. Teraz działa tak, jak pokazano na następnej migawce ekranu.

Jest prawdopodobne, że ten zbiór adnotacji Lombok byłby powszechnie pożądany, szczególnie w przypadku klas zorientowanych na dane. Z tego powodu Project Lombok udostępnia zagregowane adnotacje, takie jak @Data, które zawierają zbiór tych adnotacji. W tym przypadku mogłem uzyskać bardzo podobne zachowanie do kilku indywidualnych adnotacji, które podałem za pomocą @Data. Adnotacja @Data prowadzi do Lombok, aby zastosować @Getter do wszystkich pól i @Setter do wszystkich pól nieostatecznych. Inną główną różnicą w stosunku do tego, czego użyłem, jest to, że używa @RequiredArgsConstructor zamiast @AllArgsConstructor.

Jednym z najlepszych sposobów sprawdzenia, co Projekt Lombok zrobił ze skompilowanym plikiem .class, jest użycie javap. Pokazuje to następny zrzut ekranu.

Na tym wyjściu widzimy, że w skompilowanej klasie Person.class dostępnych jest kilka metod powszechnie postrzeganych jako standardowy kod. Istnieje dwuargumentowy konstruktor z parametrami, hashCode (), equals (Object), toString () oraz oczekiwane metody get i set.

Projekt Lombok nie jest pozbawiony obaw i ograniczeń. Wiele z nich jest wyrażonych w odpowiedziach na posty Hamleta D'Arcy'ego Java Without the Boilerplate - Project Lombok. Jednym z ograniczeń jest zmniejszona obsługa w IDE innych niż Eclipse (chociaż istnieje przyzwoita obsługa NetBeans i obsługiwany jest javac). Niepokój dotyczy potrzeby, aby inne osoby używające i utrzymujące kod uzyskały nową zależność od Lombok. Ten problem można nieco złagodzić, stosując delombok, który w razie potrzeby może zostać użyty w procesie kompilacji.

Inne artykuły i posty na blogu dotyczące projektu Lombok obejmują Project Lombok - Never Write Java Boilerplate Code Again, Java Without the Boilerplate - Project Lombok, Project Lombok: Bye Bye Boilerplate, Java Posse's Project Lombok Interview, Project Lombok: Put an End to Java Verbosity , Project Lombok - Must have in your Java Toolkit, Project Lombok: Interesting Bean Shortcuts with Adnotation Processor, Wywiad: Reinier and Roel on Lombok, Reducing Boilerplate Code with Project Lombok, Rapid Development with Lombok, Lombok Reduces Your Boilerplate Code, oraz Lepsza alternatywa dla pobierających i ustawiających.

Ta historia „Wspólna funkcjonalność obiektów Java w projekcie Lombok” została pierwotnie opublikowana przez JavaWorld.