Pular para o conteúdo principal

Melhorando a sobrescrita dos métodos equals() e hashCode()

Olá hoje iremos melhorar a forma que realizamos uma tarefa que muitos desenvolvedores não gostam de fazer, ou até mesmo deixam de lado, mas é de extrema importância para o correto funcionamento dos nossos Objetos, que é a sobrescrita dos métodos equals e hashCode().

Sobrescrita utilizando uma IDE


A maioria das IDEs realizam a tarefa de sobrescrever os métodos equals(Object o) e hashCode(), mas o código gerado não é dos melhores, vamos analisar um exemplo da geração automática usando a IDE Eclipse, segue o código:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class Cliente {

 private String cpf;
 
 public Cliente(String cpf) {
  this.cpf = cpf;
 }

 public String getCpf() {
  return cpf;
 }

 @Override
 public int hashCode() {
  final int prime = 31;
  int result = 1;
  result = prime * result + ((cpf == null) ? 0 : cpf.hashCode());
  return result;
 }

 @Override
 public boolean equals(Object obj) {
  if (this == obj)
   return true;
  if (obj == null)
   return false;
  if (getClass() != obj.getClass())
   return false;
  Cliente other = (Cliente) obj;
  if (cpf == null) {
   if (other.cpf != null)
    return false;
  } else if (!cpf.equals(other.cpf))
   return false;
  return true;
 }
}

O código acima esta bem poluído, porque a IDE adiciona vários blocos condicionais para garantir a integridade dos métodos, para confirma o funcionamento vamos criar um caso de teste usando JUnit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class ClienteTest{
 
 @Test
 public void equalsClienteTest(){
  
  Cliente cliente  = new Cliente("9876543210");
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertEquals(cliente, cliente2);
 }
 
 @Test
 public void notEqualsClienteTest(){
  
  Cliente cliente  = new Cliente("0123456789");
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertNotEquals(cliente, cliente2);
 }
 
 @Test
 public void leftNullEqualsClienteTest(){
  
  Cliente cliente  = new Cliente(null);
  Cliente cliente2 = new Cliente("9876543210");

  Assert.assertNotEquals(cliente, cliente2);
 }

 @Test
 public void rightNullEqualsClienteTest(){
  
  Cliente cliente  = new Cliente("0123456789");
  Cliente cliente2 = new Cliente(null);

  Assert.assertNotEquals(cliente, cliente2);
 }
}

Ao executar o teste, podemos notar que nossa implementação esta correta, porém a escrita do código pode melhorar.

Sobrescrita usando a classe java.util.Objects


A classe java.util.Objects possui uma porção de métodos utilitários que ajudam na manipulação de objetos variados, esta classe esta disponível a partir do Java 7, vamos analisar como esta classe pode nos ajudar a melhorar a sobrescrita do método equals(Object o) e hasCode():


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Cliente {

 private String cpf;
 
 public Cliente(String cpf) {
  this.cpf = cpf;
 }

 public String getCpf() {
  return cpf;
 }
 
 @Override
 public int hashCode(){
  return Objects.hash(this.cpf);
 }

 @Override
 public boolean equals(Object obj){
  
  if(Objects.nonNull(obj) && getClass() != obj.getClass()){
   return false;
  }
  else{
   final Cliente other = (Cliente) obj;
         
         return Objects.equals(this.cpf, other.cpf);
  }
 }
}

Executando o JUnit novamente, todos os casos de testes são executados com sucesso, e podemos notar um código bem mais limpo e simples, isso porque estamos usando os métodos Objects.hash e Objects.equals que ajudam na escrita das implementações do hashcode e equals.

Melhorando ainda mais seu Código


Mesmo usando a classe java.util.Objects,  nossa classe ainda possui um código muito vinculado a sua infraestrutura, com isso temos o famoso código boilerplate, que é aquele código repetitivo que temos que criar em todas as classes do nosso domínio, exemplo:
  • Construtores;
  • Getters e Setters;
  • hashCode();
  • equals(Object o);
  • toString().
Para melhorar isso existem uma porção de APIs e Frameworks que podem gerenciar esse tipo de tarefa:

Comentários

Postagens mais visitadas deste blog

Utilizando LocalDate, LocalDateTime e LocalTime na Prática

Tudo bem pessoal, hoje iremos avaliar e analisar operações de manipulação de Datas envolvendo a JavaTime API introduzida no Java 8.

Exemplos da java.time API
Já se passaram alguns anos desde o lançamento do Java 8 e mesmo após este período, há empresas que desconhecem o poder da java.time API, esta foi uma nova API de datas introduzida no Java 8 visando resolver problemas que tínhamos com as velhas classes Date e Calendar.

Vamos mostrar vários exemplos práticos do uso da API:
Criação de objetos No exemplo abaixo, estamos criando os objetos para manipulação de datas, perceba que temos 3 tipos, sendo LocalDate para manipular datas, LocalDateTime para manipular data/hora e LocalTime para horas:
LocalDate localDate = LocalDate.now(); LocalDateTime localDateTime = LocalDateTime.now(); LocalTime localTime = LocalTime.now();
Utilizando formatação Aqui realizamos a operação de formatação, perceba que não foi necessário utilizar a classe SimpleDateFormat, que usaríamos em conjunto com D…

Lendo e Manipulando arquivos CSV com Java

Olá hoje veremos como realizar a leitura e manipulação de arquivos CSV com Java, mostrando que as novas versões da plataforma Java deixaram algumas tarefas simples de serem realizadas.

Exemplo de Arquivo Hoje em dia é comum ao realizar integrações ou carga de dados o uso de arquivos CSV, isto porque, este arquivo possui uma estrutura de fácil entendimento e simples de manipular na maioria das plataformas de desenvolvimento.

Para realizar a leitura dos dados vamos manipular um arquivo com as seguintes colunas: namecpfagephone address:

name;cpf;age;phone;address caio;123456789;20;1145223643;AvenidaPaulista vinicius;147852369;18;1125253625;AvenidaManoel sandra;963258741;30;1174587858;RuaTeixeira regina;125478522;40;1145254536;RuaFernando fernando;785245563;42;1145253669;RuaPereira augusto;456123014;50;1125363633;AvenidaPaulinia maria;456123789;10;1125455525;AvenidaNossaSenhora
Para representar os dados em objetos Java iremos utilizar a seguinte classe:

importlombok.AllArgsConstruc…

Versionamento de Banco Dados com Flyway

Olá pessoal, hoje iremos analisar e aprender como realizar o versionamento e gerenciamento das bases de dados relacionais utilizando o framework Flyway.

Versionamento de Banco Dados Ao trabalhar com desenvolvimento de sistemas é comum realizarmos o versionamento, isso porque uma aplicação pode necessitar de correções, novas funcionalidades e evoluções, onde para garantir a compatibilidade e cuidar do seu ciclo de vida, geramos versões onde é especificado quais itens estão presentes em cada release.
Vamos imaginar seguinte cenário: Sistema ERP1.0.0: Entrega dos módulos Financeiro e RH;1.1.0: Entrega do módulo Contas a Receber. Perceba que a ideia é controlar o que cada versão possui de diferente, e para controlar essas mudanças no lado da aplicação existem várias técnicas e ferramentas, mas e para controlar as mudanças no lado do Banco de dados ? 
Para isso podemos utilizar ferramentas de versionamento que ajudam a realizar este controle, a ferramenta que iremos utilizar é o Flyway.
Con…