dev-resources.site
for different kinds of informations.
Proyecto Lombok en Java
Introducci贸n
Lombok es una librer铆a que act煤a como procesador de anotaciones para Java, dise帽ada para eliminar la redundancia en el c贸digo. Su principal funci贸n es automatizar la generaci贸n de c贸digo repetitivo o "boilerplate" - esos elementos que, aunque necesarios, no aportan valor directo a la l贸gica de nuestro programa. Principalmente, se utiliza para la generaci贸n de forma autom谩tica en tiempo de compilaci贸n de m茅todos getter y setter, constructores, m茅todos equals()
, hashCode()
, toString()
, entre otros elementos comunes en las clases Java.
En lugar de escribir manualmente decenas de l铆neas de c贸digo para estas funciones b谩sicas, Lombok permite definirlas mediante simples anotaciones, lo que resulta en un c贸digo m谩s limpio, mantenible y menos propenso a errores.
Instalaci贸n
Para utilizar Lombok en un proyecto Java, es necesario agregar la dependencia correspondiente en el archivo pom.xml
(en caso de un proyecto Maven) o build.gradle
(en caso de un proyecto Gradle), adem谩s de instalar el plugin correspondiente en el IDE que estemos utilizando. Durante este post, utilizaremos Maven e IntelliJ IDEA como ejemplo.
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<scope>provided</scope>
</dependency>
</dependencies>
En caso de alguna duda siempre se puede revisar la documentaci贸n oficial de Lombok:
@data
Cuando creamos una clase regularmente realizamos las siguientes acciones, ya sea manualmente o con alg煤n atajo que nos proporcione nuestro IDE:
- Encapsular atributos y generar sus m茅todos
getter
ysetter
- Generar un constructor vac铆o y otro que reciba todos los atributos
- Implementar los m茅todos
equals()
,hashCode()
ytoString()
Bueno, Lombok tiene la anotaci贸n @Data
que nos permite hacer todo esto en una sola l铆nea, generar todo lo relacionado con los POJO (Plain Old Java Objects). Esta anotaci贸n es una combinaci贸n de las anotaciones @Getter
, @Setter
, @EqualsAndHashCode
, @NoArgsConstructor
y @AllArgsConstructor
que veremos m谩s adelante.
import lombok.Data;
@Data
public class Persona {
private String nombre;
}
public class Main {
public static void main(String[] args) {
Persona p1 = new Persona();
p2.setNombre("Maria");
System.out.println(p1.getNombre());
}
}
@NoArgsConstructor, @AllArgsConstructor y @RequiredArgsConstructor
Estas anotaciones nos permiten generar constructores de forma autom谩tica con diferentes combinaciones de argumentos, considerando que los atributos se usan de acuerdo al orden en que fueron declarados en la clase.
-
@NoArgsConstructor
: Genera un constructor sin argumentos (vac铆o), en caso de que no sea posible generar uno, se lanzar谩 una excepci贸n, para evitarlo basta con usar la anotaci贸n de la siguiente manera@NoArgsConstructor(force = true)
. -
@AllArgsConstructor
: Genera un constructor con todos los atributos de la clase como argumentos. -
@RequiredArgsConstructor
: Genera un constructor para todos los campos finales y/o marcados con la anotaci贸n@NonNull
.
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Persona {
private String nombre;
}
@Getter y @setter
Estas anotaciones nos permiten generar los m茅todos getter
y setter
de forma autom谩tica para todos los atributos de la clase, o solo para los que sean marcados con la anotaci贸n correspondiente, es decir, pueden ser utilizadas a nivel de clase o atributo.
import lombok.*;
@Getter
@Setter
public class Persona {
private String nombre;
private String apellido;
}
import lombok.*;
public class Persona {
@Getter @Setter
private String nombre;
private String apellido;
}
@ToString
Esta anotaci贸n genera el m茅todo toString()
de forma autom谩tica, el cual retorna una representaci贸n en forma de cadena de la clase y sus atributos con el siguiente formato: NombreClase(atributo1=valor1, atributo2=valor2, ...)
. Por defecto todos los atributos no est谩ticos de la clase son incluidos en el resultado, pero se pueden excluir atributos espec铆ficos mediante el atributo @ToString.Exclude
. En caso de que solo se quiera mostrar el valor del atributo y no el nombre tal c煤al se declara, se puede usar @ToString(includeFieldNames = false)
.
import lombok.*;
@AllArgsConstructor
@ToString
public class Persona {
private String nombre;
@ToString.Exclude
private String apellido;
}
// Output: Persona(nombre=Maria)
@EqualsAndHashCode
Permite generar los m茅todos equals()
y hashCode()
a partir de todos los atributos de la clase, en caso de que se quiera excluir o incluir alg煤n atributo se puede hacer mediante la anotaci贸n @EqualsAndHashCode.Exclude
y @EqualsAndHashCode.Include
respectivamente.
import lombok.*;
@AllArgsConstructor
@EqualsAndHashCode
public class Persona {
private String nombre;
private String apellido;
@EqualsAndHashCode.Exclude
private int edad;
}
@Value
Anteriormente en Java para crear una clase inmutable era necesario realizar una serie de pasos, como hacer que la clase y/o atributos fueran del tipo final
, y que no se generar谩n los m茅todos setter
. Lombok nos facilita la creaci贸n de clases inmutables mediante la anotaci贸n @Value
, la cual combina las anotaciones @Getter
, @ToString
, @EqualsAndHashCode
y @AllArgsConstructor
para generar una clase inmutable. Todos los atributos son marcados del tipo private final
y no se generan los m茅todos setter
. Es la variante inmutable de @Data
.
import lombok.*;
@Value
public class Persona {
String nombre;
String apellido;
int edad;
}
En versiones recientes de Java esta anotaci贸n pierde sentido frente al uso de Records
, dado que tienen el mismo prop贸sito, y es m谩s pr谩ctico utilizar records. Si te interesa saber m谩s sobre este tema en el blog hay m谩s publicaciones al respecto de los records.
public record Persona(String nombre, String apellido, int edad) {}
@val
Esta anotaci贸n nos permite declarar una variable como final
y autom谩ticamente inferir su tipo de dato, es decir, no es necesario especificar el tipo de dato de la variable, Lombok se encarga de inferirlo. Es 煤til en caso de que el tipo de dato de la variable sea muy largo o complejo, de esta manera se evita repetirlo.
public static void main(String[] args) {
val str = "Hello World";
val x = 10;
}
Esta anotaci贸n puede perder sentido si utilizamos directamente final var
o simplemente var
para la inferencia de tipos, lo cual resulta m谩s c贸modo dado que es una caracter铆stica propia del lenguaje. Si te interesa saber m谩s sobe esto puede consultar el siguiente post
public static void main(String[] args) {
final var str = "Hello World";
var x = 10;
}
@var
Funciona exactamente igual que @val
, pero no declara la variable como final
, simplemente infiere su tipo. Es necesario considerar el concepto de inferencia de tipos, ya que no se puede declarar algo del tipo String
y por el hecho de que no sea final
querer asignarle un valor de tipo int
. Nuevamente, esta anotaci贸n es sustituida por var
en versiones recientes de Java.
public static void main(String[] args) {
var str = "Hello World";
var x = 10;
}
@NonNull
Esta anotaci贸n se puede utilizar en atributos de clase y par谩metros de un m茅todo, b谩sicamente indica que el valor de un atributo no puede ser nulo, en caso de que se intente asignar un valor null
a un atributo marcado con @NonNull
se lanzar谩 una excepci贸n NullPointerException
, es decir, se utiliza if (param == null) throw new NullPointerException("param is marked non-null but is null");
. Independientemente de la excepci贸n que genera, su uso es m谩s visible dentro del propio IDE, dado que este nos indicar谩 de alguna manera que este valor no puede ser nulo.
import lombok.*;
@Data
@AllArgsConstructor
public class Persona {
@NonNull
private String nombre;
private String apellido;
private int edad;
}
@Cleanup
Esta anotaci贸n permite asegurarnos de que cualquier recurso que la utilice en caso de tener un m茅todo close()
o que implemente las interfaces AutoCloseable
o Closeable
se cierre de forma autom谩tica al finalizar el bloque de c贸digo en el que se encuentra. Es 煤til en caso de trabajar con recursos que necesiten ser liberados, como archivos, conexiones a bases de datos, etc.
import lombok.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
@Cleanup
BufferedReader br = new BufferedReader(new FileReader("datos.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
Este resultado se puede obtener de forma manual si utilizamos un try with resources
.
import java.io.*;
public class Main {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("datos.txt"))){
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@builder
Esta anotaci贸n nos permite generar un patr贸n de dise帽o Builder de forma autom谩tica, es decir, un objeto que nos permite construir objetos complejos paso a paso, de forma que se puedan configurar diferentes atributos de un objeto sin tener que llamar a un constructor con muchos par谩metros. Es 煤til en caso de que una clase tenga muchos atributos y no queramos tener un constructor con muchos par谩metros.
import lombok.*;
@Builder
public class Persona {
private String nombre;
private String apellido;
private int edad;
}
@With
Esta anotaci贸n nos permite crear un m茅todo que nos devuelve una copia del objeto actual con un atributo modificado, es decir, genera un m茅todo withNombreAtributo(Object object)
que nos permite crear una copia del objeto actual con el atributo object
modificado por el valor que le pasemos como argumento. Es 煤til en caso de que queramos modificar un atributo de un objeto sin modificar el objeto original.
@With
@AllArgsConstructor
@ToString
public class Persona {
private String nombre;
private String apellido;
private int edad;
}
public static void main(String[] args) {
Persona p = new Persona("Luis", "Garc铆a", 25);
var p2 = p.withNombre("Juan");
System.out.println(p); // Persona(nombre=Luis, apellido=Garc铆a, edad=25)
System.out.println(p2); // Persona(nombre=Juan, apellido=Garc铆a, edad=25)
}
Hasta este punto hemos visto algunas de las anotaciones que se pueden llegar a utilizar con m谩s frecuencia, cada una de estas puede o no aceptar configuraciones adicionales, de igual forma existen otras que se encuentran marcadas como experimentales, en cualquiera de los casos es importante consultar la documentaci贸n oficial para obtener el m谩ximo provecho de todas las caracter铆sticas que nos ofrece Lombok y las ventajas respecto a la generaci贸n de c贸digo repetitivo.
Featured ones: