overriding predefined methods java
Este tutorial explica como substituir métodos predefinidos como equals (), hashCode (), compareTo (), etc. em Java com exemplos:
Em nosso tutorial anterior, discutimos o polimorfismo do tempo de execução em Java. O polimorfismo de tempo de execução em Java é implementado usando a substituição de método. A substituição de método envolve a redefinição do método da classe pai na subclasse.
Java tem vários métodos predefinidos como equals (), hashCode (), compareTo (), toString (), etc. que são usados comumente para objetos gerais, independentemente da classe a que pertencem. Mas para que esses métodos funcionem para todos os objetos, precisamos sobrescrever esses métodos ou redefinir suas implementações para que possam trabalhar com os dados que desejamos.
=> Visite aqui para aprender Java do zero.
Neste tutorial, discutiremos a substituição de todos esses métodos juntamente com as consequências se não substituirmos esses métodos.
O que você aprenderá:
- Substituindo métodos equals () e hashCode () em Java
- Substituindo o método estático em Java
- Substituindo compareTo () em Java
- Substituir método toString () em Java
- perguntas frequentes
- Conclusão
- Leitura recomendada
Substituindo métodos equals () e hashCode () em Java
Usamos o método equals () em Java para comparar dois objetos. Este método retorna verdadeiro quando os objetos são iguais e falso quando não são iguais.
Duas maneiras são usadas para comparar a igualdade de dois objetos.
como implementar fila em java
# 1) Comparação superficial
A comparação superficial é a implementação padrão para o método equals () definido na classe “java.lang.Object”. Como parte dessa implementação, o método equals () verificará se dois objetos que estão sendo comparados possuem referências que se referem ao mesmo objeto.
Isso significa que se obj1 e obj2 são dois objetos, então a implementação padrão do método equals () (comparação superficial) verificará apenas se as referências de obj1 e obj2 são do mesmo objeto.
Em comparação superficial, nenhum conteúdo de dados é comparado.
# 2) Comparação profunda
Em uma comparação profunda, comparamos os membros de dados de cada objeto, ou seja, os objetos são comparados em relação ao estado. Portanto, comparamos os objetos em um nível profundo, incluindo seu conteúdo.
Para comparar os objetos usando comparação profunda, geralmente substituímos o método equals ().
Agora considere o seguinte programa Java.
class Complex { private double r, i; //declare real and imaginary component as private public Complex(double r, double i) { //constructor this.r = r; this.i = i; } } public class Main { public static void main(String() args) { Complex c1 = new Complex(5, 10); //c1 object Complex c2 = new Complex(5, 10); //c2 object if (c1 == c2) { System.out.println('Two Complex objects are Equal '); } else { System.out.println('Two Complex objects are not Equal '); } } }
Resultado:
Se virmos a saída do programa acima, ele diz que os objetos não são iguais, embora o conteúdo dos dois objetos seja o mesmo. Isso porque, quando a igualdade é verificada, é determinado se os dois objetos c1 e c2 se referem ao mesmo objeto.
Como visto no programa c1 e c2 são dois objetos diferentes, portanto, são referências diferentes e, portanto, resulta assim.
Agora vamos criar uma terceira referência c3 e igualá-la a c1 da seguinte maneira:
Complexo c3 = c1;
Nesse caso, c3 e c1 se referirão ao mesmo objeto e, portanto, (c3 == c1) retornará verdadeiro.
O que o programa acima fez foi uma comparação superficial. Então, como verificamos se dois objetos têm o mesmo conteúdo?
Aqui, faremos uma comparação profunda e, para esse propósito, substituímos o método equals ().
O programa a seguir mostra a substituição do método equals (). Usamos a mesma classe Complex.
class Complex { private double r, i; public Complex(double r, double i) { this.r = r; this.i = i; } // override equals () method to compare two complex objects @Override public boolean equals(Object obj) { // returns true=>object is compared to itself if (obj == this) { return true; } //return false if obj is not an instance of Complex class if (!(obj instanceof Complex)) { return false; } // typecast obj to Complex type Complex c = (Complex) obj; // Compare the contents of two objects and return value return Double.compare(r, c.r) == 0 && Double.compare(i, c.i) == 0; } } public class Main { public static void main(String() args) { Complex c1 = new Complex(5, 10); Complex c2 = new Complex(5, 10); if (c1.equals(c2)) { System.out.println('Complex objects c1 and c2 are Equal '); } else { System.out.println('Complex objects c1 and c2 are not Equal '); } } }
Resultado:
melhores firewalls grátis para windows 10
Agora que temos um método equals () sobrescrito, quando comparamos dois objetos, a saída mostra que os dois objetos são iguais, pois seus conteúdos são os mesmos. Observe o método equals () substituído. Aqui verificamos se ambos os objetos têm a mesma referência. Caso contrário, verificamos individualmente o conteúdo desses objetos.
Em Java, sempre que substituímos o método equals (), é aconselhável substituir também o método hashCode (). Isso ocorre porque, se não substituirmos o método hashCode (), cada objeto pode ter um hashCode diferente.
Isso pode não interferir com os objetos gerais, mas certas coleções baseadas em hash como HashTable, HashSet e HashMap podem não funcionar corretamente.
O programa a seguir mostra os métodos equals () e hashCode () substituídos.
import java.io.*; import java.util.*; class EqualsHashCode { String name; int id; EqualsHashCode(String name, int id) { this.name = name; this.id = id; } @Override public boolean equals(Object obj) @Override public int hashCode() { // return current object's id as hashCode return this.id; } } class Main { public static void main (String() args) { // create two objects with same state EqualsHashCode e1 = new EqualsHashCode('Java', 1); EqualsHashCode e2 = new EqualsHashCode('Java', 1); //update the objects Map map = new HashMap(); map.put(e1, 'C++'); map.put(e2, 'Python'); //display contents for(EqualsHashCode eh : map.keySet()) { System.out.println(map.get(eh).toString()); } } }
Resultado:
Neste programa, usamos um hashMap. Substituímos os métodos equals () e hashCode (). Portanto, quando dizemos map.put (e1, “C ++”), ele faz o hash para algum local do intervalo. Em seguida, chamamos map.put (e2, “Python”). Desta vez, ele fará o hash para o mesmo depósito e substituirá o valor anterior. Isso ocorre porque substituímos o método hashCode ().
Substituindo o método estático em Java
Podemos substituir o método estático em Java?
No que diz respeito à substituição do método estático em Java, a resposta direta a esta pergunta é Não, não podemos substituir o método estático.
O método estático é invocado usando o próprio nome da classe. Não precisamos de um objeto para chamar um método estático. Portanto, mesmo se declararmos um método com o mesmo protótipo em uma subclasse, não podemos chamá-lo de override. Em vez disso, estamos apenas ocultando a definição da classe pai do método estático.
O programa Java a seguir mostra o método estático e o método não estático em um sistema de herança junto com seu comportamento em tempo de execução.
class Parent { // Parent class static method cannot be overridden by Child public static void display() { System.out.println('Parent class::static display()'); } // parent class non-static print method to be overridden by Child public void print() { System.out.println('Parent class::non-static print()'); } } // Subclass class Child extends Parent { // static display() method =>hides display() in Parent class public static void display() { System.out.println('Child class:: static display()'); } //overrides print() in Parent class public void print() { System.out.println('Child class::Non-static print()'); } } public class Main { public static void main(String args( )) { Parent new_obj = new Child(); // static methods are call as per the reference type. Since reference type //Parent, this call will execute Parent class's display method new_obj.display(); // here the print () method of Child class is called new_obj.print(); } }
Resultado:
A partir da saída do programa, podemos concluir o seguinte.
- A chamada ao método estático é sempre feita com base no tipo de referência. Daí quando chamamos new_obj. display () no programa acima, como a referência new_obj é do tipo classe Parent, o método display () da classe Parent é chamado.
- Por outro lado, os métodos não estáticos são chamados com base no conteúdo do objeto de referência com o qual o método é chamado. Portanto, no programa acima, o método new_obj.print () chama o método print () da classe filha, pois o conteúdo new_obj é o objeto da classe filha.
Isso explica a saída do programa acima e precisamos nos lembrar dos seguintes pontos também ao lidar com métodos estáticos no sistema OOP.
- Um método estático não pode ocultar um método de instância não estático e um método de instância não estático não pode substituir um método estático.
- Podemos sobrecarregar os métodos da classe pai em uma subclasse, mas eles não substituem nem ocultam os métodos da classe pai, em vez disso, são novos métodos na subclasse.
Substituindo compareTo () em Java
Sabemos que a interface java.lang.Comparable fornece um método ‘compareTo ()’ usando o qual podemos classificar os objetos em uma ordem natural, como ordem lexical para objetos String, ordem numérica para inteiros, etc.
Para implementar a classificação em objetos ou coleções definidos pelo usuário, precisamos substituir o método compareTo () para classificar os elementos da coleção ou objetos definidos pelo usuário.
Então, o que um método compareTo () faz?
Um método compareTo () deve retornar um valor positivo se o objeto atual for maior que o objeto passado na ordem e o valor negativo do objeto atual for menor que o objeto passado. Se os dois objetos forem iguais, o método compareTo () retornará zero.
Outro ponto a ser observado é que os métodos equals () e compareTo () devem se comportar de maneira consistente. Isso significa que se o método compareTo () retorna que dois objetos são iguais (retorna zero), então devemos ter a mesma saída do método equals () também.
Vamos implementar um programa Java que substitui o método compareTo (). Neste programa, estamos usando uma classe Color que possui duas variáveis privadas, ou seja, nome e id. Associámos o 'id' a cada cor e substituiremos o método compare () para organizar as cores de acordo com o id.
import java.util.*; //color class class Color implements Comparator, Comparable { private String name; private int id; Color() { } Color(String n, int id) { this.name = n; this.id = id; } public String getColorName() { return this.name; } public int getColorId() { return this.id; } // Overriding the compareTo method @Override public int compareTo(Color c) { return (this.name).compareTo(c.name); } // Overriding the compare method to sort the colors on id @Override public int compare(Color c, Color c1) { return c.id - c1.id; } } public class Main { public static void main(String args()) { // List of Colors List list = new ArrayList(); list.add(new Color('Red', 3)); list.add(new Color('Green', 2)); list.add(new Color('Blue', 5)); list.add(new Color('Orange', 4)); list.add(new Color('Yellow', 1)); Collections.sort(list); // Sorts the array list System.out.println('The list of colors:'); for(Color c: list) // print the sorted list of colors System.out.print(c.getColorName() + ', '); // Sort the array list using comparator Collections.sort(list, new Color()); System.out.println(' '); System.out.println('The sorted list of colors:'); for(Color c: list) // print the sorted list of colors as per id System.out.print(c.getColorId() + ':' + c.getColorName() + ' , '); }
Resultado:
Na saída acima, primeiro exibimos a lista de cores e, em seguida, a lista classificada de cores. No programa, substituímos os métodos compareTo () e compare ().
Substituir método toString () em Java
O método ‘toString ()’ retorna a representação String de um objeto em Java. Porém, quando temos objetos definidos pelo usuário, esse método pode se comportar de maneira diferente.
Por exemplo,considere o seguinte programa.
class Complex { private double r, i; public Complex(double r, double i) { this.r = r; this.i = i; } } public class Main { public static void main(String() args) { Complex c1 = new Complex(5, 20); //create complex class Object //print the contents of complex number System.out.println('Complex number contents: ' + c1); } }
Resultado:
Conforme mostrado neste programa, estamos exibindo o objeto da classe Complex que definimos anteriormente. No entanto, a saída mostrada não é o conteúdo, mas é bastante críptico.
A saída mostra um nome de classe Complex seguido pelo caractere ‘@’ e o hashCode do objeto. Esta é a saída padrão impressa pelo método toString () da classe Object.
Se quisermos a saída adequada, precisamos substituir o método toString () em nosso aplicativo.
O programa Java a seguir mostra como substituir o método toString () para imprimir o conteúdo do objeto Complex.
class Complex { private double r, i; public Complex(double r, double i) { this.r = r; this.i = i; } //override toString () method to return String representation of complex number @Override public String toString() { return String.format(r + ' + i ' + i); } } public class Main { public static void main(String() args) { Complex c1 = new Complex(10, 15); System.out.println('Complex Number contents: ' + c1); } }
Resultado:
O programa acima mostra que o método toString () é sobrescrito para retornar o conteúdo do objeto Complex no formato fornecido (real + i * imaginário).
Em geral, quando queremos exibir o objeto de classe usando print () ou println (), é sempre aconselhável substituir o método toString () para obter a saída apropriada.
perguntas frequentes
P # 1) Por que usar .equals em vez de == Java?
ferramentas de gerenciamento de casos de teste de código aberto
Responda: Usamos ‘==’ para comparar tipos primitivos como int, char, boolean, etc. Usamos equals () para comparar objetos (predefinidos ou definidos pelo usuário). Normalmente substituímos o método equals () para comparar dois objetos e o valor de retorno de equals () depende do código substituído.
Q # 2) Para que hashCode () e equals () são usados?
Responda: Em Java, o método equals () é usado para comparar a igualdade de dois objetos. O método hashCode () retorna o hashCode do objeto. Enquanto o método equals () é usado com a maioria dos objetos para testar sua igualdade, o hashCode é usado principalmente em coleções hash como HashTable, HashMap, HashSet, etc.
P # 3) Podemos mudar a lista de argumentos do método sobrescrito?
Responda: Não. Quando substituímos o método, mantemos a assinatura do método ou protótipo do método igual na subclasse também. Portanto, não podemos alterar o número de parâmetros no método substituído.
P # 4) Por que substituímos toString ()?
Responda: Quando o método toString () é sobrescrito, podemos retornar os valores do objeto para o qual o método toString () é sobrescrito sem escrever muito código. Isso ocorre porque o compilador java invoca o método toString () quando imprimimos um objeto.
P # 5) O que aconteceria se você não substituísse o método toString ()?
Responda: Se não substituirmos o método toString (), não obteremos nenhuma informação sobre as propriedades ou estado do objeto. Não saberemos o que realmente está dentro do objeto. Portanto, todas as classes devem substituir o método toString ().
Isso ocorre porque a implementação padrão do método toString () exibe a representação de String, mas quando usamos a implementação toString () padrão no objeto, não obteremos o conteúdo do objeto.
Conclusão
Neste tutorial, discutimos sobre como substituir alguns métodos Java predefinidos e também vimos por que precisamos substituí-los.
Quando lidamos com objetos, as implementações padrão de métodos como equals (), compareTo () e toString () podem não fornecer as informações corretas. Portanto, optamos por substituir.
=> Dê uma olhada no guia para iniciantes em Java aqui.
Leitura recomendada
- Tutorial de Java String | Métodos Java String com exemplos
- Threads Java com métodos e ciclo de vida
- Método Java String length () com exemplos
- Reverter uma matriz em Java - 3 métodos com exemplos
- Como usar o método toString Java?
- Método Java String indexOf com exemplos de código
- Java String contains () Tutorial de método com exemplos
- Método Java String Split () - Como dividir uma string em Java