Schreiben Sie fettfreien Java-Code mit Project Lombok
Veröffentlicht: 2022-03-11Es gibt eine Reihe von Tools und Bibliotheken, ohne die ich mir heutzutage nicht mehr vorstellen kann, Java-Code zu schreiben. Traditionell gehören Dinge wie Google Guava oder Joda Time (zumindest für die Ära vor Java 8) zu den Abhängigkeiten, die ich am Ende die meiste Zeit in meine Projekte werfe, unabhängig von der jeweiligen Domäne.
Lombok verdient sicherlich auch seinen Platz in meinen POMs oder Gradle-Builds, obwohl es kein typisches Bibliotheks-/Framework-Dienstprogramm ist. Lombok gibt es schon eine ganze Weile (Erstveröffentlichung 2009) und ist seitdem sehr gereift. Ich hatte jedoch immer das Gefühl, dass es mehr Aufmerksamkeit verdient – es ist eine erstaunliche Art, mit der natürlichen Ausführlichkeit von Java umzugehen.
In diesem Beitrag werden wir untersuchen, was Lombok zu einem so praktischen Werkzeug macht.
Java hat viele Dinge zu bieten, die über die JVM selbst hinausgehen, die eine bemerkenswerte Software ist. Java ist ausgereift und leistungsfähig, und die Community und das Ökosystem drumherum sind riesig und lebendig.
Als Programmiersprache hat Java jedoch einige Eigenheiten sowie Designentscheidungen, die es ziemlich ausführlich machen können. Fügen Sie einige Konstrukte und Klassenmuster hinzu, die wir Java-Entwickler häufig verwenden müssen, und wir erhalten häufig viele Codezeilen, die wenig oder keinen wirklichen Wert haben, außer der Einhaltung einiger Einschränkungen oder Framework-Konventionen.
Hier kommt Lombok ins Spiel. Es ermöglicht uns, die Menge an „Boilerplate“-Code, den wir schreiben müssen, drastisch zu reduzieren. Die Schöpfer von Lombok sind ein paar sehr schlaue Typen und haben sicherlich einen Sinn für Humor – Sie dürfen dieses Intro, das sie auf einer vergangenen Konferenz gemacht haben, nicht verpassen!
Mal sehen, wie Lombok seine Magie vollbringt und einige Anwendungsbeispiele.
Wie Lombok funktioniert
Lombok fungiert als Annotationsprozessor, der zur Kompilierzeit Code zu Ihren Klassen „hinzufügt“. Die Anmerkungsverarbeitung ist eine Funktion, die dem Java-Compiler in Version 5 hinzugefügt wurde. Die Idee ist, dass Benutzer Anmerkungsprozessoren (von sich selbst geschrieben oder über Abhängigkeiten von Drittanbietern wie Lombok) in den Build-Klassenpfad einfügen können. Wenn der Compiler dann während des Kompiliervorgangs eine Anmerkung findet, fragt er sozusagen: „Hey, jemand im Klassenpfad, der an dieser @Annotation interessiert ist?“. Für diese Prozessoren, die ihre Hand heben, überträgt der Compiler ihnen dann die Kontrolle zusammen mit dem Kompilierungskontext, den sie, nun ja, verarbeiten können.
Der vielleicht häufigste Fall für Annotationsprozessoren ist das Generieren neuer Quelldateien oder das Durchführen von Prüfungen zur Kompilierzeit.
Lombok fällt nicht wirklich in diese Kategorien: Es modifiziert lediglich die Compiler-Datenstrukturen, die zur Darstellung des Codes verwendet werden; dh sein abstrakter Syntaxbaum (AST). Durch die Modifikation des AST des Compilers verändert Lombok indirekt die endgültige Bytecode-Generierung selbst.
Dieser ungewöhnliche und ziemlich aufdringliche Ansatz hat traditionell dazu geführt, dass Lombok als eine Art Hacker angesehen wird. Auch wenn ich dieser Charakterisierung bis zu einem gewissen Grad zustimmen würde, würde ich Lombok eher als „kluge, technisch verdienstvolle und originelle Alternative“ betrachten, anstatt es im schlechten Sinne des Wortes zu sehen.
Dennoch gibt es Entwickler, die es für einen Hack halten und Lombok aus diesem Grund nicht verwenden. Das ist verständlich, aber meiner Erfahrung nach überwiegen die Produktivitätsvorteile von Lombok alle diese Bedenken. Ich benutze es seit vielen Jahren gerne für Produktionsprojekte.
Bevor ich ins Detail gehe, möchte ich die zwei Gründe zusammenfassen, warum ich den Einsatz von Lombok in meinen Projekten besonders schätze:
- Lombok hilft dabei, meinen Code sauber, prägnant und auf den Punkt zu bringen. Ich finde meine annotierten Lombok-Klassen sehr ausdrucksstark und ich finde annotierten Code im Allgemeinen ziemlich aufschlussreich, obwohl nicht jeder im Internet unbedingt zustimmt.
- Wenn ich ein Projekt beginne und über ein Domänenmodell nachdenke, beginne ich in der Regel mit dem Schreiben von Klassen, die in hohem Maße in Arbeit sind und die ich iterativ ändere, wenn ich weiter denke und sie verfeinere. In diesen frühen Stadien hilft mir Lombok, mich schneller zu bewegen, da ich mich nicht bewegen oder den für mich generierten Boilerplate-Code umwandeln muss.
Bohnenmuster und gemeinsame Objektmethoden
Viele der von uns verwendeten Java-Tools und -Frameworks basieren auf dem Bean Pattern. Java Beans sind serialisierbare Klassen, die einen Standardkonstruktor mit null Argumenten (und möglicherweise andere Versionen) haben und ihren Zustand über Getter und Setter offenlegen, die normalerweise durch private Felder unterstützt werden. Wir schreiben viele davon, zum Beispiel wenn wir mit JPA oder Serialisierungs-Frameworks wie JAXB oder Jackson arbeiten.
Betrachten Sie diese User-Bean, die bis zu fünf Attribute (Eigenschaften) enthält, für die wir einen zusätzlichen Konstruktor für alle Attribute, eine sinnvolle Zeichenfolgendarstellung und die Definition von Gleichheit/Hashing in Bezug auf ihr E-Mail-Feld hätten möchten:
public class User implements Serializable { private String email; private String firstName; private String lastName; private Instant registrationTs; private boolean payingCustomer; // Empty constructor implementation: ~3 lines. // Utility constructor for all attributes: ~7 lines. // Getters/setters: ~38 lines. // equals() and hashCode() as per email: ~23 lines. // toString() for all attributes: ~3 lines. // Relevant: 5 lines; Boilerplate: 74 lines => 93% meaningless code :( }Der Kürze halber habe ich hier, anstatt die tatsächliche Implementierung aller Methoden einzubeziehen, stattdessen nur Kommentare bereitgestellt, die die Methoden und die Anzahl der Codezeilen auflisten, die die tatsächlichen Implementierungen erforderten. Dieser Boilerplate-Code hätte mehr als 90 % des Codes für diese Klasse ausgemacht!
Wenn ich später beispielsweise E-Mail in E- email emailAddress oder registrationTs ein Date anstelle eines Instant haben wollte, müsste ich Zeit aufwenden (in einigen Fällen zugegebenermaßen mit Hilfe meiner IDE), um Dinge wie Get zu ändern / setze Methodennamen und -typen, ändere meinen Hilfskonstruktor und so weiter. Wieder unbezahlbare Zeit für etwas, das meinem Code keinen praktischen Geschäftswert bringt.
Mal sehen, wie Lombok hier helfen kann:
import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @ToString @EqualsAndHashCode(of = {"email"}) public class User { private String email; private String firstName; private String lastName; private Instant registrationTs; private boolean payingCustomer; } Voila! Ich habe einfach ein paar lombok.* Anmerkungen hinzugefügt und genau das erreicht, was ich wollte. Die obige Auflistung ist genau der gesamte Code, den ich dafür schreiben muss. Lombok hängt sich in meinen Compiler-Prozess ein und generiert alles für mich (siehe Screenshot unten in meiner IDE).
Wie Sie sehen, erkennt der NetBeans-Inspektor (und dies geschieht unabhängig von der IDE) den kompilierten Klassen-Bytecode, einschließlich der Hinzufügungen, die Lombok in den Prozess eingebracht hat. Was hier passiert ist ganz einfach:
- Mit
@Getterund@Setterhabe ich Lombok angewiesen, Getter und Setter für alle Attribute zu generieren. Dies liegt daran, dass ich die Anmerkungen auf Klassenebene verwendet habe. Wenn ich selektiv angeben wollte, was für welche Attribute generiert werden soll, hätte ich die Felder selbst mit Anmerkungen versehen können. - Dank
@NoArgsConstructorund@AllArgsConstructorhabe ich einen leeren Standardkonstruktor für meine Klasse sowie einen zusätzlichen für alle Attribute erhalten. - Die
@ToString-Annotation generiert automatisch eine praktischetoString()-Methode, die standardmäßig alle Klassenattribute mit vorangestelltem Namen anzeigt. - Um schließlich das Methodenpaar
equals()undhashCode()in Bezug auf das E-Mail-Feld zu definieren, habe ich@EqualsAndHashCodeverwendet und es mit der Liste der relevanten Felder (in diesem Fall nur die E-Mail) parametrisiert.
Anpassen von Lombok-Anmerkungen
Lassen Sie uns nun einige Lombok-Anpassungen nach demselben Beispiel verwenden:
- Ich möchte die Sichtbarkeit des Standardkonstruktors verringern. Da ich es nur aus Gründen der Bean-Konformität benötige, erwarte ich, dass Verbraucher der Klasse nur den Konstruktor aufrufen, der alle Felder übernimmt. Um dies zu erzwingen, passe ich den generierten Konstruktor mit
AccessLevel.PACKAGE. - Ich möchte sicherstellen, dass meinen Feldern niemals Nullwerte zugewiesen werden, weder über den Konstruktor noch über die Setter-Methoden. Es reicht aus, Klassenattribute mit
@NonNullzu kommentieren; Lombok generiert Nullprüfungen, dieNullPointerException, wenn dies in den Konstruktor- und Setter-Methoden angemessen ist. - Ich füge ein
passwordhinzu, möchte aber aus Sicherheitsgründen nicht, dass es beim Aufruf vontoString()angezeigt wird. Dies wird über das Excludes-Argument von@ToString. - Ich bin damit einverstanden, den Zustand über Getter öffentlich zugänglich zu machen, würde es aber vorziehen, die äußere Veränderlichkeit einzuschränken. Also lasse ich
@Getter, verwende aber wiederAccessLevel.PROTECTEDfür@Setter. - Vielleicht möchte ich dem E-
email-Feld eine Einschränkung auferlegen, damit bei Änderungen eine Art Überprüfung durchgeführt wird. Dazu implementiere ich einfach die MethodesetEmail()selbst. Lombok wird die Generierung für eine bereits vorhandene Methode einfach auslassen.
So sieht die User-Klasse dann aus:
import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"email"}) public class User { private @NonNull String email; private @NonNull byte[] password; private @NonNull String firstName; private @NonNull String lastName; private @NonNull Instant registrationTs; private boolean payingCustomer; protected void setEmail(String email) { // Check for null (=> NullPointerException) // and valid email code (=> IllegalArgumentException) this.email = email; } }Beachten Sie, dass wir für einige Anmerkungen Klassenattribute als einfache Zeichenfolgen angeben. Kein Problem, denn Lombok wirft einen Kompilierungsfehler, wenn wir uns beispielsweise vertippen oder auf ein nicht vorhandenes Feld verweisen. Mit Lombok sind wir sicher.
Genau wie bei der Methode setEmail() ist Lombok auch in Ordnung und generiert nichts für eine Methode, die der Programmierer bereits implementiert hat. Dies gilt für alle Methoden und Konstruktoren.
Unveränderliche Datenstrukturen
Ein weiterer Anwendungsfall, in dem sich Lombok auszeichnet, ist die Erstellung unveränderlicher Datenstrukturen. Diese werden normalerweise als „Werttypen“ bezeichnet. Einige Sprachen haben dafür eingebaute Unterstützung, und es gibt sogar einen Vorschlag, dies in zukünftige Java-Versionen zu integrieren.
Angenommen, wir möchten eine Reaktion auf eine Benutzeranmeldungsaktion modellieren. Dies ist die Art von Objekt, das wir einfach instanziieren und an andere Schichten der Anwendung zurückgeben möchten (z. B. um JSON als Hauptteil einer HTTP-Antwort zu serialisieren). Eine solche LoginResponse müsste überhaupt nicht veränderbar sein und Lombok kann helfen, dies prägnant zu beschreiben. Sicher, es gibt viele andere Anwendungsfälle für unveränderliche Datenstrukturen (sie sind unter anderem Multithreading- und Cache-freundlich), aber bleiben wir bei diesem einfachen Beispiel:
import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.ToString; import lombok.experimental.Wither; @Getter @RequiredArgsConstructor @ToString @EqualsAndHashCode public final class LoginResponse { private final long userId; private final @NonNull String authToken; private final @NonNull Instant loginTs; @Wither private final @NonNull Instant tokenExpiryTs; }Bemerkenswert hier:

- Eine
@RequiredArgsConstructorAnmerkung wurde eingeführt. Treffend benannt, generiert es einen Konstruktor für alle finalen Felder, die noch nicht initialisiert wurden. - In Fällen, in denen wir eine zuvor ausgegebene LoginResonse wiederverwenden möchten (stellen Sie sich beispielsweise eine „Refresh Token“-Operation vor), möchten wir sicherlich nicht unsere vorhandene Instanz ändern, sondern darauf basierend eine neue generieren . Sehen Sie, wie uns die
@WitherAnnotation hier hilft: Sie weist Lombok an, einewithTokenExpiryTs(Instant tokenExpiryTs)-Methode zu generieren, die eine neue Instanz von LoginResponse mit allen with'ed-Instanzwerten erstellt, mit Ausnahme des neuen, den wir angeben. Möchten Sie dieses Verhalten für alle Felder? Fügen Sie stattdessen einfach@Witherzur Klassendeklaration hinzu.
@Daten und @Wert
Beide bisher diskutierten Anwendungsfälle sind so häufig, dass Lombok ein paar Annotationen mitliefert, um sie noch kürzer zu machen: Das Annotieren einer Klasse mit @Data wird Lombok veranlassen, sich so zu verhalten, als wäre es mit @Getter + @Setter + @ToString + annotiert worden @EqualsAndHashCode + @RequiredArgsConstructor . Ebenso verwandelt die Verwendung von @Value Ihre Klasse in eine unveränderliche (und endgültige) Klasse, auch wieder so, als ob sie mit der obigen Liste kommentiert worden wäre.
Builder-Muster
Zurück zu unserem Benutzerbeispiel: Wenn wir eine neue Instanz erstellen möchten, müssen wir einen Konstruktor mit bis zu sechs Argumenten verwenden. Dies ist bereits eine ziemlich große Zahl, die noch schlimmer wird, wenn wir der Klasse weitere Attribute hinzufügen. Angenommen, wir möchten einige Standardwerte für die Felder lastName und payingCustomer .
Lombok implementiert eine sehr leistungsstarke @Builder Funktion, die es uns ermöglicht, ein Builder-Pattern zu verwenden, um neue Instanzen zu erstellen. Fügen wir es unserer User-Klasse hinzu:
import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"email"}) @Builder public class User { private @NonNull String email; private @NonNull byte[] password; private @NonNull String firstName; private @NonNull String lastName = ""; private @NonNull Instant registrationTs; private boolean payingCustomer = false; }Jetzt können wir neue Benutzer wie folgt fließend erstellen:
User user = User .builder() .email("[email protected]") .password("secret".getBytes(StandardCharsets.UTF_8)) .firstName("Miguel") .registrationTs(Instant.now()) .build();Es ist leicht vorstellbar, wie praktisch dieses Konstrukt wird, wenn unsere Klassen wachsen.
Delegierung/Komposition
Wenn Sie der sehr vernünftigen Regel „Bevorzugung der Komposition der Vererbung“ folgen wollen, hilft Java dabei nicht wirklich, was die Ausführlichkeit betrifft. Wenn Sie Objekte erstellen möchten, müssen Sie normalerweise überall delegierende Methodenaufrufe schreiben.
Lombok schlägt hierfür eine Lösung über @Delegate . Schauen wir uns ein Beispiel an.
Stellen Sie sich vor, wir möchten ein neues Konzept von ContactInformation . Dies sind einige Informationen, über die unser User verfügt, und wir möchten möglicherweise, dass andere Klassen diese auch haben. Wir können dies dann über eine Schnittstelle wie diese modellieren:
public interface HasContactInformation { String getEmail(); String getFirstName(); String getLastName(); } Wir würden dann eine neue ContactInformation -Klasse mit Lombok einführen:
import lombok.Data; @Data public class ContactInformation implements HasContactInformation { private String email; private String firstName; private String lastName; } Und schließlich könnten wir den User so umgestalten, dass er mit ContactInformation komponiert und Lombok verwendet, um alle erforderlichen Delegierungsaufrufe zu generieren, die dem Schnittstellenvertrag entsprechen:
import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; import lombok.experimental.Delegate; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"contactInformation"}) public class User implements HasContactInformation { @Getter(AccessLevel.NONE) @Delegate(types = {HasContactInformation.class}) private final ContactInformation contactInformation = new ContactInformation(); private @NonNull byte[] password; private @NonNull Instant registrationTs; private boolean payingCustomer = false; } Beachten Sie, dass ich keine Implementierungen für die Methoden von HasContactInformation schreiben musste: Dies ist etwas, das wir Lombok mitteilen, indem wir Aufrufe an unsere ContactInformation Instanz delegieren.
Da ich nicht möchte, dass die delegierte Instanz von außen zugänglich ist, passe ich sie mit einem @Getter(AccessLevel.NONE) an und verhindere effektiv die Getter-Generierung dafür.
Geprüfte Ausnahmen
Wie wir alle wissen, unterscheidet Java zwischen geprüften und ungeprüften Ausnahmen. Dies ist eine traditionelle Quelle für Kontroversen und Kritik an der Sprache, da die Behandlung von Ausnahmen uns dadurch manchmal zu sehr in die Quere kommt, insbesondere wenn es um APIs geht, die darauf ausgelegt sind, geprüfte Ausnahmen auszulösen und uns daher Entwickler zwingen, sie entweder abzufangen oder unsere Methoden dafür zu deklarieren wirf sie.
Betrachten Sie dieses Beispiel:
public class UserService { public URL buildUsersApiUrl() { try { return new URL("https://apiserver.com/users"); } catch (MalformedURLException ex) { // Malformed? Really? throw new RuntimeException(ex); } } } Dies ist ein so häufiges Muster: Wir wissen sicherlich, dass unsere URL wohlgeformt ist, aber – weil der URL -Konstruktor eine überprüfte Ausnahme auslöst – sind wir entweder gezwungen, sie abzufangen oder unsere Methode zu deklarieren, um sie auszuwerfen und Aufrufer in der gleichen Situation auszugeben. Das Einschließen dieser geprüften Ausnahmen in eine RuntimeException ist eine sehr erweiterte Vorgehensweise. Und dies wird noch schlimmer, wenn die Anzahl der geprüften Ausnahmen, mit denen wir umgehen müssen, während des Codierens zunimmt.
Das ist also genau das, wofür Lomboks @SneakyThrows ist, es wird alle geprüften Ausnahmen, die in unserer Methode geworfen werden sollen, in eine ungeprüfte umhüllen und uns von dem Ärger befreien:
import lombok.SneakyThrows; public class UserService { @SneakyThrows public URL buildUsersApiUrl() { return new URL("https://apiserver.com/users"); } }Protokollierung
Wie oft fügen Sie Loggerinstanzen wie diese zu Ihren Klassen hinzu? (SLF4J-Beispiel)
private static final Logger LOG = LoggerFactory.getLogger(UserService.class);Ich vermute ziemlich viel. In diesem Wissen haben die Ersteller von Lombok eine Anmerkung implementiert, die eine Protokollierungsinstanz mit einem anpassbaren Namen (standardmäßig log) erstellt und die gängigsten Protokollierungs-Frameworks auf der Java-Plattform unterstützt. Einfach so (wieder SLF4J-basiert):
import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @Slf4j public class UserService { @SneakyThrows public URL buildUsersApiUrl() { log.debug("Building users API URL"); return new URL("https://apiserver.com/users"); } }Kommentieren von generiertem Code
Wenn wir Lombok zum Generieren von Code verwenden, scheint es, als würden wir die Möglichkeit verlieren, diese Methoden zu kommentieren, da wir sie nicht wirklich schreiben. Aber das ist nicht wirklich wahr. Stattdessen erlaubt uns Lombok, ihm zu sagen, wie generierter Code kommentiert werden soll, wobei wir, um ehrlich zu sein, eine etwas seltsame Notation verwenden.
Betrachten Sie dieses Beispiel, das auf die Verwendung eines Abhängigkeitsinjektionsframeworks abzielt: Wir haben eine UserService -Klasse, die die Konstruktorinjektion verwendet, um die Verweise auf ein UserRepository und einen UserApiClient .
package com.mgl.toptal.lombok; import javax.inject.Inject; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor(onConstructor = @__(@Inject)) public class UserService { private final UserRepository userRepository; private final UserApiClient userApiClient; // Instead of: // // @Inject // public UserService(UserRepository userRepository, // UserApiClient userApiClient) { // this.userRepository = userRepository; // this.userApiClient = userApiClient; // } }Das obige Beispiel zeigt, wie ein generierter Konstruktor kommentiert wird. Lombok ermöglicht es uns, dasselbe auch für generierte Methoden und Parameter zu tun.
Mehr lernen
Die in diesem Beitrag erläuterte Verwendung von Lombok konzentriert sich auf die Funktionen, die ich persönlich im Laufe der Jahre als am nützlichsten empfunden habe. Es sind jedoch viele andere Funktionen und Anpassungen verfügbar.
Die Dokumentation von Lombok ist sehr informativ und gründlich. Sie haben spezielle Seiten für jedes einzelne Feature (Anmerkung) mit sehr detaillierten Erklärungen und Beispielen. Wenn Sie diesen Beitrag interessant finden, ermutige ich Sie, tiefer in Lombok und seine Dokumentation einzutauchen, um mehr zu erfahren.
Die Projektseite dokumentiert, wie man Lombok in verschiedenen Programmierumgebungen verwendet. Kurz gesagt, die gängigsten IDEs (Eclipse, NetBeans und IntelliJ) werden unterstützt. Ich selbst wechsle regelmäßig projektweise von einem zum anderen und verwende Lombok für alle fehlerfrei.
Delombok!
Delombok ist Teil der „Lombok Toolchain“ und kann sich als sehr nützlich erweisen. Was es tut, ist im Grunde genommen, den Java -Quellcode für Ihren annotierten Lombok-Code zu generieren und dieselben Operationen auszuführen, die der von Lombok generierte Bytecode ausführt.
Dies ist eine großartige Option für Leute, die erwägen, Lombok zu adoptieren, sich aber noch nicht ganz sicher sind. Sie können es frei verwenden und es gibt kein „Vendor Lock-in“. Falls Sie oder Ihr Team später die Wahl bereuen, können Sie jederzeit mit delombok den entsprechenden Quellcode generieren, den Sie dann ohne verbleibende Abhängigkeit von Lombok verwenden können.
Delombok ist auch ein großartiges Werkzeug, um genau zu erfahren, was Lombok tun wird. Es gibt sehr einfache Möglichkeiten, es in Ihren Build-Prozess einzubinden.
Alternativen
Es gibt viele Tools in der Java-Welt, die Annotationsprozessoren ähnlich nutzen, um Ihren Code zur Kompilierzeit anzureichern oder zu ändern, wie z. B. Immutables oder Google Auto Value. Diese (und sicher auch andere!) überschneiden sich funktionsmäßig mit Lombok. Besonders der Immutables-Ansatz gefällt mir sehr gut und habe ihn auch schon in einigen Projekten eingesetzt.
Es ist auch erwähnenswert, dass es andere großartige Tools gibt, die ähnliche Funktionen für die „Bytecode-Verbesserung“ bieten, wie etwa Byte Buddy oder Javassist. Diese funktionieren jedoch normalerweise zur Laufzeit und umfassen eine eigene Welt, die über den Rahmen dieses Beitrags hinausgeht.
Prägnantes Java
Es gibt eine Reihe moderner, auf JVM ausgerichteter Sprachen, die idiomatischere – oder sogar sprachliche – Designansätze bieten, die dabei helfen, einige der gleichen Probleme anzugehen. Sicherlich sind Groovy, Scala und Kotlin nette Beispiele. Aber wenn Sie an einem reinen Java-Projekt arbeiten, dann ist Lombok ein nettes Werkzeug, um Ihre Programme prägnanter, ausdrucksstärker und wartbarer zu machen.
