Só falta de atenção:
Conta conta1 = new ContaCorrente("0000", 99, 999); // criou uma conta diferente de qualquer conta criada no for
banco.adiciona(conta1); // mas você adicionou a conta ao banco
banco.temConta(conta1); // como foi adicionado ao banco, o método temConta vai encontrá-la
Depende, quais os critérios que você tem para pesquisar uma conta?
Você pode criar um método para pesquisar uma Conta
pelo titular dessa forma:
public Conta pesquisarPorTitular(String titular) {
for (Conta conta : contas) {
if (titular.equals(conta.getTitular())) {
return conta;
}
}
return null;
}
O nome que você dá às suas variáveis não interfere em nada.
Seu vetor não guarda nomes, ele guarda referências dos objetos, isto é, os endereços de memória das suas instâncias.
Se você escrever um progrtama com o método main
abaixo:
public static void main(String[] args) {
Conta conta1 = new ContaCorrente("0000", 99, 999); // criar um objeto conta1
Conta conta2 = new ContaCorrente("0000", 99, 999); // criar um objeto conta2 com as mesmas informações que conta1
Conta conta3 = new ContaCorrente("0000", 99, 999); // criar um objeto conta3 com as mesmas informações que conta1 e conta2
Conta conta4 = new ContaCorrente("4444", 44, 444); // criar um objeto conta4 difertente de todos os anteriores
System.out.println("conta1 igual a conta2: " + conta1.equals(conta2)); // qual será a saída?
System.out.println("conta1 igual a conta3: " + conta1.equals(conta3)); // qual será a saída?
System.out.println("conta1 igual a conta4: " + conta1.equals(conta4)); // qual será a saída?
System.out.println("conta2 igual a conta3: " + conta2.equals(conta3)); // qual será a saída?
System.out.println("conta2 igual a conta4: " + conta2.equals(conta4)); // qual será a saída?
System.out.println("conta3 igual a conta4: " + conta3.equals(conta4)); // qual será a saída?
}
Após executá-lo, a saída será essa:
conta1 igual a conta2: false
conta1 igual a conta3: false
conta1 igual a conta4: false
conta2 igual a conta3: false
conta2 igual a conta4: false
conta3 igual a conta4: false
Porque ele imprimiu false
pra todo mundo sendo que os objetos conta1
, conta2
e conta3
são iguais?
O que determina se um objeto é “igual” à outro é a forma como foi implementado o método equals
da classe do objeto.
A implementação padrão do método equals retorna true
quando o objeto passado por parâmetro é a mesma referência de memória do objeto onde o método equals
foi chamado, ou seja, a implementação padrão do equals
é assim:
public boolean equals(Object object) {
return this == object;
}
Entretanto, esse método deve ser sobrescrito quando você tem critérios distintos para comparar os objetos de uma classe.
Por exemplo, para que dois objetos da classe Conta
sejam considerados iguais, eles deveriam ter os mesmo conteúdo nos atributos id
, saldo
, titular
, agencia
e numero
.
A implementação do equals
ficaria assim:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Conta)) {
return false;
}
Conta that = (Conta) obj;
if (this.agencia != that.agencia) {
return false;
}
if (this.id != that.id) {
return false;
}
if (this.numero != that.numero) {
return false;
}
if (Double.doubleToLongBits(this.saldo) != Double.doubleToLongBits(that.saldo)) {
return false;
}
if (this.titular == null) {
if (that.titular != null) {
return false;
}
} else if (!this.titular.equals(that.titular)) {
return false;
}
return true;
}
Ao sobrescrever o método equals
entra em questão uma regra de que também se deve sobrescrever o método hashcode
de forma a calcular o hash
levando em conta os mesmos atributos que são considerados no equals
, então o método hashcode
da classe Conta
deveria ser assim:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + agencia;
result = prime * result + id;
result = prime * result + numero;
long temp;
temp = Double.doubleToLongBits(saldo);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((titular == null) ? 0 : titular.hashCode());
return result;
}
Agora com os métodos equals
e hashcode
devidamente implementados, vamos executar novamente o método main
que cria as 3 contas.
O resultado será:
conta1 igual a conta2: false
conta1 igual a conta3: false
conta1 igual a conta4: false
conta2 igual a conta3: false
conta2 igual a conta4: false
conta3 igual a conta4: false
Como assim?
Sobrescrevi o método equals e ele imprimiu novamente false
, mesmo os objetos conta1
, conta2
e conta3
sendo iguais.
O que aconteceu?
Antes de continuar falando sobre o equals
, vamos dar uma olhada no construtor da sua classe Conta
:
public Conta(String titular, int agencia, int numero) {
this.titular = titular;
this.agencia = agencia;
this.numero = numero;
Conta.total = Conta.total + 1;
this.id = total;
}
Perceba que para cada objeto Conta
que é instanciado, você já atribui um novo id
para ele.
Esse id
é um número interno do objeto, tanto que você nem possui métodos para modificá-lo.
Nesse caso, o ideal é você remover o atributo id
dos critérios de comparação do equals
e hashcode
, dessa forma:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Conta)) {
return false;
}
Conta that = (Conta) obj;
if (this.agencia != that.agencia) {
return false;
}
if (this.numero != that.numero) {
return false;
}
if (Double.doubleToLongBits(this.saldo) != Double.doubleToLongBits(that.saldo)) {
return false;
}
if (this.titular == null) {
if (that.titular != null) {
return false;
}
} else if (!this.titular.equals(that.titular)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + agencia;
result = prime * result + numero;
long temp;
temp = Double.doubleToLongBits(saldo);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + ((titular == null) ? 0 : titular.hashCode());
return result;
}
Agora, se executar aquele método main
novamente, teremos a seguinte saída:
conta1 igual a conta2: true
conta1 igual a conta3: true
conta1 igual a conta4: false
conta2 igual a conta3: true
conta2 igual a conta4: false
conta3 igual a conta4: false
Perceba que desta vez a saída está correta, pois cada comparação do objeto conta4
retorna false
pois ele realmente é diferente dos objetos conta1
, conta2
e conta3
.
Agora com o equals
e hashcode
consistentes, veja como a classe Banco
funciona bem:
public static void main(String[] args) {
Conta conta1 = new ContaCorrente("0000", 99, 999); // criar um objeto conta1
Conta conta2 = new ContaCorrente("0000", 99, 999); // criar um objeto conta2 com as mesmas informações que conta1
Conta conta3 = new ContaCorrente("0000", 99, 999); // criar um objeto conta3 com as mesmas informações que conta1 e conta2
Conta conta4 = new ContaCorrente("4444", 44, 444); // criar um objeto conta4 difertente de todos os anteriores
Banco banco = new Banco("BB", 999); // criar um objeto banco
banco.adiciona(conta1); // adicionar no banco somente o objeto conta1
System.out.println("tem conta1 " + banco.temConta(conta1)); // qual será a saída?
System.out.println("tem conta2 " + banco.temConta(conta2)); // qual será a saída?
System.out.println("tem conta3 " + banco.temConta(conta3)); // qual será a saída?
System.out.println("tem conta4 " + banco.temConta(conta4)); // qual será a saída?
}
Ao executar o código acima, a saída será:
tem conta1 true
tem conta2 true
tem conta3 true
tem conta4 false