overriding predefined methods java
Aquest tutorial explica com anul·lar mètodes predefinits com equals (), hashCode (), compareTo (), etc. a Java amb exemples:
Al nostre tutorial anterior, vam parlar del polimorfisme en temps d'execució a Java. El polimorfisme en temps d'execució a Java s'implementa utilitzant mètodes de substitució. La substitució del mètode consisteix a redefinir el mètode de la classe pare a la subclasse.
Java té diversos mètodes predefinits com equals (), hashCode (), compareTo (), toString (), etc. que s'utilitzen habitualment per a objectes generals independentment de la classe a la qual pertanyin. Però perquè aquests mètodes funcionin per a tots els objectes, hem de substituir aquests mètodes o redefinir-ne les implementacions perquè puguin treballar amb les dades que desitgem.
=> Visiteu aquí per aprendre Java des de zero.
En aquest tutorial, analitzarem la substitució de tots aquests mètodes juntament amb les conseqüències si no anul·lem aquests mètodes.
Què aprendreu:
- Overriding equals () I hashCode () Mètodes a Java
- Mètode estàtic primordial a Java
- CompareTo () general a Java
- Substitueix el mètode toString () a Java
- Preguntes freqüents
- Conclusió
- Lectura recomanada
Overriding equals () I hashCode () Mètodes a Java
Utilitzem el mètode equals () a Java per comparar dos objectes. Aquest mètode torna cert quan els objectes són iguals i fals quan no són iguals.
S’utilitzen dues maneres de comparar la igualtat de dos objectes.
# 1) Comparació poc profunda
La comparació superficial és la implementació predeterminada per al mètode equals () definit a la classe 'java.lang.Object'. Com a part d'aquesta implementació, el mètode equals () comprovarà si dos objectes que es comparen tenen referències referents al mateix objecte.
Això vol dir que si obj1 i obj2 són dos objectes, la implementació per defecte del mètode equals () (comparació superficial) només comprovarà si les referències d’object1 i obj2 provenen del mateix objecte.
En comparacions superficials, no es comparen continguts de dades.
# 2) Comparació profunda
En una comparació profunda, comparem els membres de dades de cada objecte, és a dir, els objectes es comparen respecte a l’estat. Per tant, comparem els objectes a un nivell profund, inclòs el seu contingut.
Per comparar els objectes mitjançant una comparació profunda, generalment anul·lem el mètode equals ().
Ara considerem el següent 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 '); } } }
Sortida:
Si veiem la sortida del programa anterior, es diu que els objectes no són iguals tot i que el contingut dels dos objectes és el mateix. Això es deu al fet que, quan es comprova la igualtat, es determina si els dos objectes c1 i c2 fan referència al mateix objecte.
Com es pot veure al programa c1 i c2 són dos objectes diferents, de manera que són referències diferents i, per tant, resulta així.
Ara anem a crear una tercera referència c3 i equiparem-la a c1 de la manera següent:
Complex c3 = c1;
En aquest cas, c3 i c1 faran referència al mateix objecte i, per tant, (c3 == c1) tornarà cert.
El que va fer el programa anterior va ser la comparació superficial. Llavors, com comprovem si dos objectes tenen el mateix contingut?
Aquí fem una comparació profunda i, amb aquest propòsit, anul·lem el mètode equals ().
El programa següent mostra la substitució del mètode equals (). Utilitzem la mateixa 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 '); } } }
Sortida:
Ara que tenim un mètode overridden equals (), quan comparem dos objectes, la sortida mostra que els dos objectes són iguals ja que el seu contingut és el mateix. Tingueu en compte el mètode overridden equals (). Aquí comprovem si tots dos objectes tenen la mateixa referència. Si no, comprovem individualment el contingut d’aquests objectes.
A Java, sempre que anul·lem el mètode equals (), és aconsellable anul·lar també el mètode hashCode (). Això es deu al fet que si no anul·lem el mètode hashCode (), cada objecte pot tenir hashCode diferent.
Pot ser que això no interfereixi amb els objectes generals, però és possible que algunes col·leccions basades en hash com HashTable, HashSet i HashMap no funcionin correctament.
El següent programa mostra mètodes iguals () i hashCode () anul·lats.
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()); } } }
Sortida:
En aquest programa, fem servir un hashMap. Hem anul·lat els mètodes equals () i hashCode (). Per tant, quan diem map.put (e1, “C ++”), es fa una hash a alguna ubicació de dipòsit. A continuació, anomenem map.put (e2, 'Python'). Aquesta vegada tindrà hash al mateix dipòsit i substituirà el valor anterior. Això es deu al fet que hem anul·lat el mètode hashCode ().
Mètode estàtic primordial a Java
Podem anul·lar el mètode estàtic a Java?
Pel que fa a la substitució del mètode estàtic a Java, la resposta directa a aquesta pregunta és No, no podem anul·lar el mètode estàtic.
El mètode estàtic s’invoca mitjançant el propi nom de la classe. No necessitem cap objecte per anomenar un mètode estàtic. Per tant, fins i tot si declarem un mètode amb el mateix prototip en una subclasse, no el podem anomenar primordial. En lloc d'això, només amagem la definició de classe pare del mètode estàtic.
El següent programa Java mostra el mètode estàtic i el mètode no estàtic en un sistema d'herència juntament amb el seu comportament en temps d'execució.
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(); } }
Sortida:
A partir de la sortida del programa, podem concloure el següent.
- La crida al mètode estàtic sempre es fa en funció del tipus de referència. Per tant, quan vam trucar a new_obj. display () al programa anterior, ja que la referència new_obj és de la classe tipus Parent, es diu el mètode display () de la classe Parent.
- D’altra banda, s’anomenen mètodes no estàtics basats en el contingut de l’objecte de referència amb el qual s’anomena el mètode. Per tant, en el programa anterior, el mètode new_obj.print () crida al mètode print () de la classe fill, ja que el contingut new_obj és l'objecte de la classe fill.
Això explica la sortida del programa anterior i també hem de recordar els punts següents mentre tractem mètodes estàtics al sistema OOP.
- Un mètode estàtic no pot amagar un mètode d’instància no estàtica i un mètode d’instància no estàtica no pot anul·lar un mètode estàtic.
- Podem sobrecarregar els mètodes de la classe pare en una subclasse, però no anul·len ni oculten els mètodes de la classe pare, sinó que són mètodes nous de la subclasse.
CompareTo () general a Java
Sabem que la interfície java.lang.Comparable proporciona un mètode ‘compareTo ()’ mitjançant el qual podem ordenar els objectes en un ordre natural com l’ordre lèxic per als objectes String, l’ordre numèric per als nombres enters, etc.
Per implementar l'ordenació en objectes o col·leccions definits per l'usuari, hem de substituir el mètode compareTo () per ordenar els elements de col·lecció o objectes definits per l'usuari.
Llavors, què fa un mètode compareTo ()?
Un mètode compareTo () ha de retornar un valor positiu si l’objecte actual és superior a l’objecte passat per ordre i el valor negatiu de l’objecte actual és inferior a l’objecte passat. Si tots dos objectes són iguals, el mètode compareTo () retornarà zero.
Un altre punt a tenir en compte és que el mètode equals () i compareTo () haurien de comportar-se de manera coherent entre si. Això significa que si el mètode compareTo () retorna que dos objectes són iguals (retorna zero), també hauríem de tenir la mateixa sortida del mètode equals ().
Implantem un programa Java que substitueix el mètode compareTo (). En aquest programa, fem servir una classe de color que té dues variables privades, és a dir, nom i identificador. Hem associat l’identificador amb cada color i substituirem el mètode compare () per ordenar els colors segons l’identificador.
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() + ' , '); }
Sortida:
A la sortida anterior, mostrem primer la llista de colors i després la llista ordenada de colors. Al programa, hem substituït els mètodes compareTo () i compare ().
Substitueix el mètode toString () a Java
El mètode ‘toString ()’ retorna la representació de cadena d’un objecte a Java. Però quan tenim objectes definits per l'usuari, aquest mètode pot tenir un comportament diferent.
Per exemple,tingueu en compte el programa següent.
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); } }
Sortida:
Com es mostra en aquest programa, mostrem l'objecte de classe Complex que hem definit anteriorment. Tot i això, la sortida que es mostra no és el contingut, sinó que és més aviat críptica.
La sortida mostra un nom de classe Complex seguit del caràcter ‘@’ i, a continuació, el codi hash de l’objecte. Aquesta és la sortida per defecte impresa pel mètode toString () de la classe Object.
Si volem la sortida adequada, hem de substituir el mètode toString () a la nostra aplicació.
El següent programa Java mostra com anul·lar el mètode toString () per imprimir el contingut de l'objecte 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); } }
Sortida:
El programa anterior mostra que el mètode toString () està anul·lat per retornar el contingut de l'objecte Complex en el format donat (imaginari real + i *).
En general, quan volem mostrar l'objecte de classe utilitzant print () o println (), sempre és aconsellable anul·lar el mètode toString () per obtenir la sortida adequada.
Preguntes freqüents
P # 1) Per què utilitzar .equals en lloc de == Java?
Resposta: Utilitzem ‘==’ per comparar tipus primitius com int, char, booleà, etc. Utilitzem equals () per comparar objectes (predefinits o definits per l’usuari). Normalment anul·lem el mètode equals () per comparar dos objectes i el valor retornat dels iguals () depèn del codi anul·lat.
P # 2) Per a què s’utilitza hashCode () i equals ()?
Resposta: A Java, el mètode equals () s’utilitza per comparar la igualtat de dos objectes. El mètode hashCode () retorna el hashCode de l'objecte. Tot i que el mètode equals () s’utilitza amb la majoria d’objectes per provar la seva igualtat, el hashCode s’utilitza principalment en col·leccions de hash com HashTable, HashMap, HashSet, etc.
P # 3) Podem canviar la llista d'arguments del mètode anul·lat?
Resposta: No. Quan anul·lem el mètode, també mantenim la signatura del mètode o el prototip del mètode a la subclasse. Per tant, no podem canviar el nombre de paràmetres del mètode anul·lat.
com crear un nou projecte en eclipsi
Q # 4) Per què substituïm toString ()?
Resposta: Quan s’anul·la el mètode toString (), podem retornar els valors de l’objecte per al qual s’ha substituït el mètode toString () sense escriure massa codi. Això es deu al fet que el compilador Java invoca el mètode toString () quan imprimim un objecte.
P # 5) Què passaria si no anul·leu el mètode toString ()?
Resposta: Si no anul·lem el mètode toString (), no obtindrem cap informació sobre les propietats o l’estat de l’objecte. No sabrem què hi ha realment dins de l'objecte. Per tant, totes les classes haurien d’anul·lar el mètode toString ().
Això es deu a que la implementació per defecte del mètode toString () mostra la representació de cadena, però quan fem servir la implementació predeterminada de toString () a l'objecte, no obtindrem el contingut de l'objecte.
Conclusió
En aquest tutorial, hem discutit sobre la substitució d'alguns mètodes predefinits de Java i també hem vist per què hem de substituir-los.
Quan tractem objectes, és possible que les implementacions per defecte de mètodes com equals (), compareTo () i toString () no proporcionin la informació correcta. Per tant, apostem per la prioritat.
=> Feu una ullada a la guia per a principiants de Java aquí.
Lectura recomanada
- Tutorial de cadenes de Java | Mètodes de cadena Java amb exemples
- Fils de Java amb mètodes i cicle de vida
- Java String length () Mètode amb exemples
- Inverteix una matriu a Java: 3 mètodes amb exemples
- Com s'utilitza el mètode Java toString?
- Java String indexOf Method amb exemples de codi
- Java String conté () Tutorial de mètode amb exemples
- Mètode Java String Split (): com es pot dividir una cadena a Java