Uma classe java eventualmente pode ficar enorme. Sei que não é o ideal mas pode acontecer, não algo com milhares de linhas semelhante ao que pode acontecer em linguagens não orientadas a objetos, mas uma quantidade que fique um pouco desconfortável para ler na tela. Para pegar essa ideia dê uma olhada nesse exemplo:
import java.util.Date;
import java.util.Objects;
public class Pessoa { public Pessoa(String nome, String cpf, String apelido, Date dataNascimento, int idade) {
this.nome = nome;
this.cpf = cpf;
this.apelido = apelido;
this.dataNascimento = dataNascimento;
this.idade = idade;
} private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public String getApelido() {
return apelido;
}
public void setApelido(String apelido) {
this.apelido = apelido;
}
public Date getDataNascimento() {
return dataNascimento;
}
public void setDataNascimento(Date dataNascimento) {
this.dataNascimento = dataNascimento;
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
this.idade = idade;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pessoa pessoa = (Pessoa) o;
return idade == pessoa.idade &&
Objects.equals(nome, pessoa.nome) &&
Objects.equals(cpf, pessoa.cpf) &&
Objects.equals(apelido, pessoa.apelido) &&
Objects.equals(dataNascimento, pessoa.dataNascimento);
}
@Override
public int hashCode() {
return Objects.hash(nome, cpf, apelido, dataNascimento, idade);
}
@Override
public String toString() {
return "Pessoa{" +
"nome='" + nome + '\'' +
", cpf='" + cpf + '\'' +
", apelido='" + apelido + '\'' +
", dataNascimento=" + dataNascimento +
", idade=" + idade +
'}';
}
}
Essa é uma classe simples que representa uma pessoa em um programa java. Agora, repare que eu não coloquei dados de endereço, cidade de nascimento etc. Essas informações gerariam classes parecidas e mais linhas nessa mesma classe.
Agora repare na mesma classe usando anotações do Lombok:
import lombok.*;
import java.util.Date;
@ToString
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
}
Muito menor né? Ficou mais fácil para ler.
Agora que a ideia foi passada, vamos instalar e ver um pouco do que o Lombok pode nos oferecer.
Instalando:
O site do lombok é esse: https://projectlombok.org/, mas para utilizá-lo em um projeto maven basta adicionar a dependência no pom.xml:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Feito isso, o jar do lombok será adicionado ao projeto por causa do gerenciamento de dependências do maven.
Difícil né?
Bora usar essas anotações então.
@ Getter e @ Setter
Sobre “@ Getter” e “@ Setter” : São as anotações que fornecem os métodos getters e setters para atributos privados.
@Getter
@Setter
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
}
Essas anotações podem ter um parâmatro para indicar o tipo de acesso aos dados (public ou protected), então elas podem ficar assim:
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
}
As anotações desse jeito significam isso:
import lombok.*;
import java.util.Date;
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
protected String getNome() {
return nome;
}
protected void setNome(String nome) {
this.nome = nome;
}
protected String getCpf() {
return cpf;
}
protected void setCpf(String cpf) {
this.cpf = cpf;
}
protected String getApelido() {
return apelido;
}
protected void setApelido(String apelido) {
this.apelido = apelido;
}
protected Date getDataNascimento() {
return dataNascimento;
}
protected void setDataNascimento(Date dataNascimento) {
this.dataNascimento = dataNascimento;
}
protected int getIdade() {
return idade;
}
protected void setIdade(int idade) {
this.idade = idade;
}}
Também podem ser usadas em cima do atributo, dependendo da lógica/finalidade utilizada.
@ NonNull
Essa anotação fornece um teste rápido pra verificar se um atributo é nulo, ajudando a evitar NullPointerException.
Exemplo de uso:
import lombok.*;
import java.util.Date;
@ToString
@Getter
@Setter
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
@ ToString
Essa anotação gera uma implementação do método toString. É Só isso.
Exemplo de uso:
import lombok.*;
import java.util.Date;
@ToString
@Getter
@Setter
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
}
@ EqualsAndHashCode
Fornece os métodos equals() e hachCode().
É possível personalizar os atributos que serão validados, exemplos de uso:
import lombok.*;
import java.util.Date;
@ToString
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(exclude={"dataNascimento","idade"})
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
Ou:
@ToString
@Getter
@Setter
@EqualsAndHashCode
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;}
@ Data
Essa anotação é a combinação das anotações: @ ToString, @EqualsAndHashCode, @ Getter e @ Setter. Também fornece a geração de construtores, adicionando um construtor público que leva qualquer campo @NonNull ou final como parâmetros.
Mas como já visto aqui, caso queira personalizar melhor os métodos é aconselhável usar as anotações de cada funcionalidade com seus parâmetros.
@ NoArgsConstructor
Fornece a criação de um construtor vazio, exemplo de uso:
@ToString
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@NoArgsConstructor
@EqualsAndHashCode
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
Código equivalente:
@ToString
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@EqualsAndHashCode(exclude={"dataNascimento","idade"})
public class Pessoa {
public Pessoa (){
}
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
@ AllArgsConstructor
Fornece a criação de um construtor com todos os atributos, exemplo de uso:
@ToString
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Pessoa {
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
Código equivalente:
@ToString
@Getter(AccessLevel.PROTECTED)
@Setter(AccessLevel.PROTECTED)
@EqualsAndHashCode(exclude={"dataNascimento","idade"})
public class Pessoa {
public Pessoa(String nome, String cpf, String apelido, Date dataNascimento, int idade, Endereco endereco) {
this.nome = nome;
this.cpf = cpf;
this.apelido = apelido;
this.dataNascimento = dataNascimento;
this.idade = idade;
this.endereco = endereco;
}
private String nome;
private String cpf;
private String apelido;
private Date dataNascimento;
private int idade;
@NonNull
private Endereco endereco;
}
É possível definir o tipo de acesso do construtor gerado, se liga nesse print:
Também é possível a criação de um construtor estático:
Por fim, trouxe mais duas anotações bem úteis.
@ RequiredArgsConstructor
Essa anotação é muito útil na hora de fazer a injeção de dependência, exemplo de uso:
@Component
@RequiredArgsConstructor
public class PessoaGatewayImpl {
private final PessoaRepository pessoaRepository;
public void save(Pessoa pessoa){
pessoaRepository.save(pessoa);
}
}
O objeto do tipo final foi injetado via construtor usando essa anotação. Pode ser usada para substituir “@ AutoWired” e “@ Inject”.
@ Slf4j
Cria o atributo private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger (PessoaGatewayImpl.class). Exemplo de uso:
@Slf4j
@Component
@RequiredArgsConstructor
public class PessoaGatewayImpl {
private final PessoaRepository pessoaRepository;
public void save(Pessoa pessoa){
log.info("Armazenando informação.");
pessoaRepository.save(pessoa);
}
}
Código equivalente:
import br.com.example.entity.Pessoa;
import br.com.example.gateway.database.repository.PessoaRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class PessoaGatewayImpl {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger (PessoaGatewayImpl.class);
private final PessoaRepository pessoaRepository;
public void save(Pessoa pessoa){
log.info("Armazenando informação.");
pessoaRepository.save(pessoa);
}
}
O Lombok tem mais anotações, mas no dia a dia costumo usar essas dentro dos programas que desenvolvo.
Esse código está no github: https://github.com/mmarcosab/lombokexample mas não esperem nada dele além das coisas vistas nesse texto.
Até mais.
Fontes: https://projectlombok.org/