Funzionalità comuni degli oggetti Java con Project Lombok

Project Lombok è una piccola libreria che può essere utilizzata per ridurre la quantità di codice Java boilerplate comunemente scritto per le classi Java. Project Lombok lo fa tramite annotazioni che possono essere aggiunte alla classe Java per la quale sono desiderati metodi comuni. La maggior parte delle annotazioni sono auto-descrittive nei loro nomi: @Getter, @Setter, @EqualsAndHashCode, @ToString e @NoArgsConstructor sono esempi. In questo post, dimostro l'applicazione di semplici annotazioni Lombok per aggiungere questi metodi comunemente scritti a una classe Java.

Ecco una semplice classe senza una versione sovrascritta predefinita di toString ().

toString-less Person.java

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

Quando viene generata la classe precedente e viene chiamato il suo metodo ereditato implicitamente (da Object) toString (), l'output è simile a quello mostrato nell'immagine successiva.

Potremmo scrivere un metodo toString () esplicito o utilizzare Project Lombok. Il frammento di codice successivo mostra l'approccio del progetto Lombok.

Person.java con l'annotazione @ToString di Lombok

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

Di seguito viene mostrato l'output della stampa del contenuto di questa classe con una stringa toString () fornita da Lombok.

C'è una migliore rappresentazione toString () dell'oggetto Person ora, ma i suoi campi non sono ancora inizializzati, quindi vediamo solo valori nulli. Possiamo usare di nuovo Lombok per creare il costruttore.

Person.java con l'annotazione @AllArgsConstructor di 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; } 

Ora posso (in effetti, devo) passare i parametri dopo l'istanziazione dell'oggetto Person. I risultati sono mostrati nell'immagine della schermata successiva. In questo caso, il mio codice client (Main.java) mostra un errore in fase di compilazione in NetBeans perché NetBeans non crede che ci sia un costruttore in Person che accetta due stringhe. Nonostante i segni rossi ondulati, il codice viene compilato quando chiedo a NetBeans di crearlo.

Una classe come Person.java è spesso una classe di dati che dovrà essere utilizzata nei confronti e possibilmente chiavi di raccolta basate su hashCode. È importante creare correttamente le implementazioni equals (Object) e hashCode () e assicurarsi che vengano create insieme. Poiché ci sono metodi di default equals e hashCode forniti dalla classe Object padre, il codice Java che utilizza le istanze Person sarà in grado di eseguire equals e / o hashCode, ma è improbabile che siano ciò che si vuole veramente. Quando la classe eseguibile Main viene modificata nel listato di codice successivo, vediamo l'output dopo quello che ci dice che il confronto di uguaglianza viene eseguito completamente in base all'identità piuttosto che al contenuto.

Main.java That Tests equals () Implementation

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!"); } } } 

Questo non è quasi mai quello che si vuole qui. È invece richiesta un'implementazione esplicita di uguale. Mi piace il fatto che l'annotazione Lombok per questo, @EqualsAndHashCode, generi entrambi insieme solo perché non ha senso sovrascriverli esplicitamente individualmente. L'elenco della classe Person.java viene mostrato di seguito con l'aggiunta dell'annotazione @EqualsAndHashCode.

Person.java con @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; } 

L'output è migliore ora.

Non ho ancora un buon modo per accedere separatamente a ciascun campo pubblico, se necessario. Ad esempio, se volessi fare qualcosa nel mio codice in base al cognome, non ho un buon modo per arrivarci senza fare passi drastici. Posso usare di nuovo Lombok qui.

Per questo esempio, supponiamo di aver assunto erroneamente che solo il cognome della persona potrebbe cambiare. A causa di questo presupposto, forniremo solo un'annotazione Lombok @Setter per il cognome, ma forniremo un'annotazione @Getter per entrambi i campi. Successivamente viene visualizzato il codice persona modificato.

Person.java con @Getter e @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; } 

Ecco la classe Main aggiornata per eseguire questo esempio:

Main.java che fa uso di 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()); } } 

Ho dovuto commentare la chiamata per impostare il nome della persona in modo che il codice venisse compilato. Ora funziona come mostrato nell'istantanea della schermata successiva.

È probabile che questa raccolta di annotazioni di Lombok sia comunemente desiderata, specialmente per le classi orientate ai dati. Per questo motivo, Project Lombok fornisce annotazioni aggregate come @Data che forniscono una raccolta di queste annotazioni. In questo caso, avrei potuto ottenere un comportamento molto simile alle diverse annotazioni individuali che ho fornito utilizzando @Data. L'annotazione @Data fa sì che Lombok applichi @Getter a tutti i campi e @Setter a tutti i campi non finali. L'altra grande differenza rispetto a quello che ho usato è che utilizza @RequiredArgsConstructor anziché @AllArgsConstructor.

Uno dei modi migliori per vedere cosa ha fatto Project Lombok al file .class compilato è usare javap. Questo è mostrato nell'istantanea della schermata successiva.

Vediamo in questo output che un gruppo dei metodi comunemente visti come codice boilerplate sono disponibili nel Person.class compilato. C'è un costruttore con parametri a due argomenti, hashCode (), equals (Object), toString () e i metodi get e set previsti.

Il progetto Lombok non è privo di preoccupazioni e limitazioni. Molti di questi sono articolati nelle risposte al post Java Without the Boilerplate - Project Lombok di Hamlet D'Arcy. Una limitazione è il supporto ridotto negli IDE diversi da Eclipse (sebbene esista un discreto supporto per NetBeans e javac sia supportato). Una preoccupazione è la necessità che altri utilizzino e mantengano il codice per avere una nuova dipendenza da Lombok. Questa preoccupazione può essere in qualche modo attenuata attraverso l'uso del delombok, che potrebbe essere utilizzato nel processo di costruzione se necessario.

Altri articoli e post di blog che trattano il progetto Lombok includono il progetto Lombok - Non scrivere mai più codice Java Boilerplate, Java senza boilerplate - Progetto Lombok, Progetto Lombok: Bye Bye Boilerplate, Intervista su Project Lombok di Java Posse, Progetto Lombok: Metti fine alla verbosità Java , Project Lombok - A Must-Have in Your Java Toolkit, Project Lombok: Interesting Bean Shortcuts with Annotation Processor, Interview: Reinier and Roel on Lombok, Reducing Boilerplate Code with Project Lombok, Rapid Development with Lombok, Lombok Reduces Your Boilerplate Code, e Migliore alternativa per Getters e Setter.

Questa storia, "Funzionalità oggetto Java comune con Project Lombok" è stata originariamente pubblicata da JavaWorld.