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().
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:
Ao executar o teste, podemos notar que nossa implementação esta correta, porém a escrita do código pode melhorar.
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.
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:
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
- 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:
- Lombok (https://projectlombok.org/);
- Immutables (http://immutables.github.io/);
- AutoValue (https://github.com/google/auto/blob/master/value/userguide/index.md).
Até a próxima.
https://docs.oracle.com/javase/7/docs/api/java/util/Objects.html
http://junit.org/junit4/
Referências
http://junit.org/junit4/
Comentários
Postar um comentário