Funcionalidad común de objetos Java con Project Lombok

Project Lombok es una pequeña biblioteca que se puede usar para reducir la cantidad de código Java repetitivo que se escribe comúnmente para las clases de Java. Project Lombok hace esto a través de anotaciones que se pueden agregar a la clase Java para la que se desean métodos comunes. La mayoría de las anotaciones son autodescriptivas en sus nombres: @Getter, @Setter, @EqualsAndHashCode, @ToString y @NoArgsConstructor son ejemplos. En esta publicación, demuestro cómo aplicar anotaciones simples de Lombok para agregar estos métodos comúnmente escritos a una clase Java.

Aquí hay una clase simple sin una versión anulada predefinida de toString ().

toString-less Person.java

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

Cuando se genera la clase anterior y se llama a su método toString () heredado implícitamente (de Object), la salida se ve como la que se muestra en la siguiente imagen.

Podríamos escribir un método toString () explícito o usar Project Lombok. El siguiente fragmento de código demuestra el enfoque del Proyecto Lombok.

Person.java con la anotación @ToString de Lombok

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

A continuación se muestra el resultado de imprimir el contenido de esta clase con un toString () proporcionado por Lombok.

Ahora hay una mejor representación toString () del objeto Person, pero sus campos aún no están inicializados, por lo que solo vemos valores nulos. Podemos usar Lombok nuevamente para crear el constructor.

Person.java con la anotación @AllArgsConstructor de 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; } 

Ahora puedo (de hecho, debo) pasar parámetros al crear una instancia del objeto Person. Los resultados se muestran en la siguiente imagen de pantalla. En este caso, mi código de cliente (Main.java) muestra un error en tiempo de compilación en NetBeans porque NetBeans no cree que haya un constructor en Person que acepte dos cadenas. A pesar de las marcas onduladas rojas, el código se construye cuando le pido a NetBeans que lo construya.

Una clase como Person.java es a menudo una clase de datos que deberá usarse en comparaciones y posiblemente claves de colección basadas en hashCode. Es importante crear implementaciones equals (Object) y hashCode () correctamente y asegurarse de que se creen juntas. Debido a que existen métodos predeterminados equals y hashCode proporcionados por la clase Object principal, el código Java que usa instancias de Person podrá realizar iguales y / o hashCode, pero no es probable que sean lo que uno realmente quiere. Cuando la clase ejecutable Main se cambia a la siguiente lista de código, vemos la salida después de la que nos dice que la comparación de igualdad se realiza completamente en función de la identidad en lugar del contenido.

Main.java que prueba la implementación igual a ()

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

Esto casi nunca es lo que se busca aquí. En cambio, se requiere una implementación igual explícita. Me gusta el hecho de que la anotación de Lombok para esto, @EqualsAndHashCode, solo genera ambos juntos porque no tiene sentido anularlos explícitamente individualmente. La lista de clases Person.java se muestra a continuación con la adición de la anotación @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; } 

La salida es mejor ahora.

Todavía no tengo una buena forma de acceder a cada campo público por separado si es necesario. Por ejemplo, si quisiera hacer algo en mi código basado en el apellido, no tengo una buena manera de hacerlo sin tomar medidas drásticas. Puedo usar Lombok aquí nuevamente.

Para este ejemplo, supondremos que asumimos erróneamente que solo podría cambiar el apellido de la persona. Debido a esta suposición, solo proporcionaremos una anotación Lombok @Setter para el apellido, pero proporcionaremos una anotación @Getter para ambos campos. El código de persona cambiado se muestra a continuación.

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

Aquí está la clase Main actualizada para ejecutar este ejemplo:

Main.java que hace uso del nuevo 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()); } } 

Tuve que comentar la llamada para establecer el nombre de la persona para que el código se compilara. Ahora se ejecuta como se muestra en la siguiente captura de pantalla.

Es probable que esta colección de anotaciones de Lombok sea comúnmente deseada, especialmente para clases orientadas a datos. Por esta razón, Project Lombok proporciona anotaciones agregadas como @Data que proporcionan una colección de estas anotaciones. En este caso, podría haber obtenido un comportamiento muy similar a las varias anotaciones individuales que proporcioné usando @Data. La anotación @Data lleva a Lombok a aplicar @Getter a todos los campos y @Setter a todos los campos no finales. La otra gran diferencia de lo que usé es que usa @RequiredArgsConstructor en lugar de @AllArgsConstructor.

Una de las mejores formas de ver lo que Project Lombok ha hecho con el archivo .class compilado es usar javap. Esto se muestra en la siguiente captura de pantalla.

Vemos en esta salida que muchos de los métodos que comúnmente se ven en un código repetitivo están disponibles en Person.class compilado. Hay un constructor parametrizado de dos argumentos, hashCode (), equals (Object), toString () y los métodos get y set esperados.

Project Lombok no está exento de preocupaciones y limitaciones. Muchos de estos se articulan en respuestas a la publicación de Hamlet D'Arcy Java Without the Boilerplate - Project Lombok. Una limitación es el soporte reducido en IDE distintos de Eclipse (aunque existe un soporte decente para NetBeans y es compatible con javac). Una preocupación es la necesidad de que otros usen y mantengan el código para tener una nueva dependencia de Lombok. Esta preocupación se puede mitigar un poco mediante el uso del delombok, que podría usarse en el proceso de compilación si es necesario.

Otros artículos y publicaciones de blog que cubren el Proyecto Lombok incluyen el Proyecto Lombok - Nunca vuelva a escribir el código repetitivo de Java, Java sin el código repetitivo - Proyecto Lombok, Proyecto Lombok: Bye Bye Boilerplate, Entrevista al Proyecto Lombok de Java Posse, Proyecto Lombok: Poner fin a la verbosidad de Java , Project Lombok: imprescindible en su kit de herramientas de Java, Project Lombok: atajos interesantes de Bean con procesador de anotaciones, Entrevista: Reinier y Roel en Lombok, Reducción del código repetitivo con Project Lombok, Desarrollo rápido con Lombok, Lombok reduce su código repetitivo, y Mejor alternativa para Getters y Setters.

Esta historia, "Funcionalidad común de objetos Java con Project Lombok", fue publicada originalmente por JavaWorld.