overriding predefined methods java
W tym samouczku wyjaśniono, jak przesłonić predefiniowane metody, takie jak equals (), hashCode (), compareTo () itp. W Javie z przykładami:
W naszym poprzednim samouczku omówiliśmy polimorfizm środowiska uruchomieniowego w Javie. Polimorfizm w czasie wykonywania w Javie jest implementowany przy użyciu nadpisywania metody. Zastępowanie metod obejmuje ponowne zdefiniowanie metody klasy nadrzędnej w podklasie.
Java ma różne predefiniowane metody, takie jak equals (), hashCode (), compareTo (), toString () itp., Które są powszechnie używane w przypadku obiektów ogólnych, niezależnie od tego, do jakiej klasy należą. Ale aby te metody działały dla wszystkich obiektów, musimy je zastąpić lub przedefiniować ich implementacje, tak aby mogły pracować z danymi, których potrzebujemy.
=> Odwiedź tutaj, aby nauczyć się języka Java od podstaw.
W tym samouczku omówimy nadpisanie wszystkich tych metod wraz z konsekwencjami, jeśli nie zastąpimy tych metod.
Czego się nauczysz:
- Zastępowanie metod equals () i hashCode () w Javie
- Zastępowanie metody statycznej w Javie
- Przesłanianie compareTo () w Javie
- Zastąp metodę toString () w języku Java
- Często Zadawane Pytania
- Wniosek
- rekomendowane lektury
Zastępowanie metod equals () i hashCode () w Javie
Do porównania dwóch obiektów używamy metody equals () w Javie. Ta metoda zwraca wartość true, gdy obiekty są równe i false, gdy nie są równe.
Do porównania równości dwóch obiektów używane są dwa sposoby.
# 1) Płytkie porównanie
Płytkie porównanie jest domyślną implementacją metody equals () zdefiniowanej w klasie „java.lang.Object”. W ramach tej implementacji metoda equals () sprawdzi, czy dwa porównywane obiekty mają odniesienia odwołujące się do tego samego obiektu.
Oznacza to, że jeśli obj1 i obj2 są dwoma obiektami, to domyślna implementacja metody equals () (płytkie porównanie) sprawdzi tylko, czy odwołania do obj1 i obj2 pochodzą z tego samego obiektu.
W płytkim porównaniu nie porównuje się zawartości danych.
# 2) Głębokie porównanie
W głębokim porównaniu porównujemy składowe danych każdego obiektu, tj. Obiekty są porównywane pod względem stanu. Więc porównujemy obiekty na głębokim poziomie, łącznie z zawartością.
jak zgrać dvd za darmo
Aby porównać obiekty za pomocą głębokiego porównania, zwykle zastępujemy metodę equals ().
Rozważmy teraz następujący program 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 '); } } }
Wynik:
Jeśli widzimy dane wyjściowe powyższego programu, mówi on, że obiekty nie są równe, mimo że zawartość dwóch obiektów jest taka sama. Dzieje się tak, ponieważ gdy sprawdzana jest równość, określa się, czy dwa obiekty c1 i c2 odnoszą się do tego samego obiektu.
Jak widać w programie c1 i c2 są dwoma różnymi obiektami, więc są różnymi odniesieniami i dlatego tak jest.
Teraz stwórzmy trzecie odniesienie c3 i zrównajmy je z c1 w następujący sposób:
Kompleks c3 = c1;
W tym przypadku c3 i c1 będą odnosić się do tego samego obiektu, a zatem (c3 == c1) zwróci wartość true.
To, co zrobił powyższy program, było płytkim porównaniem. Jak więc sprawdzić, czy dwa obiekty mają taką samą zawartość?
Tutaj przechodzimy do głębokiego porównania iw tym celu nadpisujemy metodę equals ().
Poniższy program przedstawia przesłanianie metody equals (). Używamy tej samej klasy 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 '); } } }
Wynik:
Teraz, gdy mamy nadpisaną metodę equals (), porównując dwa obiekty, wynik pokazuje, że oba obiekty są równe, ponieważ ich zawartość jest taka sama. Zwróć uwagę na nadpisaną metodę equals (). Tutaj sprawdzamy, czy oba obiekty mają to samo odniesienie. Jeśli nie, to indywidualnie sprawdzamy zawartość tych obiektów.
W Javie, ilekroć nadpisujemy metodę equals (), zaleca się przesłonięcie również metody hashCode (). Dzieje się tak, ponieważ jeśli nie nadpisujemy metody hashCode (), każdy obiekt może mieć inny hashCode.
Może to nie kolidować z ogólnymi obiektami, ale niektóre kolekcje oparte na skrótach, takie jak HashTable, HashSet i HashMap, mogą nie działać poprawnie.
Poniższy program pokazuje nadpisane metody equals () i hashCode ().
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()); } } }
Wynik:
W tym programie używamy hashMap. Zastąpiliśmy obie metody equals () i hashCode (). Więc kiedy mówimy map.put (e1, „C ++”), to hashuje do jakiejś lokalizacji zasobnika. Następnie nazywamy map.put (e2, „Python”). Tym razem hashuje do tego samego zasobnika i zastępuje poprzednią wartość. Dzieje się tak, ponieważ zmieniliśmy metodę hashCode ().
Zastępowanie metody statycznej w Javie
Czy możemy zastąpić metodę statyczną w Javie?
Jeśli chodzi o przesłonięcie metody statycznej w Javie, bezpośrednią odpowiedzią na to pytanie jest nie, nie możemy przesłonić metody statycznej.
Metoda statyczna jest wywoływana przy użyciu samej nazwy klasy. Nie potrzebujemy obiektu do wywołania metody statycznej. Więc nawet jeśli zadeklarujemy metodę z tym samym prototypem w podklasie, nie możemy nazwać jej przesłanianiem. Zamiast tego po prostu ukrywamy definicję klasy nadrzędnej metody statycznej.
Poniższy program w języku Java przedstawia metodę statyczną i metodę niestatyczną w systemie dziedziczenia oraz ich zachowanie w czasie wykonywania.
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(); } }
Wynik:
Na podstawie wyników programu możemy wywnioskować, co następuje.
- Wywołanie metody statycznej jest zawsze dokonywane na podstawie typu odwołania. Stąd, kiedy nazwaliśmy new_obj. display () w powyższym programie, ponieważ odwołanie new_obj jest typu klasy Parent, wywoływana jest metoda display () klasy Parent.
- Z drugiej strony metody niestatyczne są wywoływane na podstawie zawartości obiektu referencyjnego, z którym wywoływana jest metoda. Stąd w powyższym programie metoda new_obj.print () wywołuje metodę print () klasy potomnej, ponieważ zawartość new_obj jest obiektem tej klasy.
To wyjaśnia wynik powyższego programu i musimy pamiętać również o następujących punktach podczas pracy z metodami statycznymi w systemie OOP.
- Metoda statyczna nie może ukryć niestatycznej metody instancji, a niestatyczna metoda instancji nie może przesłonić metody statycznej.
- Możemy przeciążyć metody z klasy nadrzędnej w podklasie, ale nie przesłaniają one ani nie ukrywają metod klasy nadrzędnej, są raczej nowymi metodami w podklasie.
Przesłanianie compareTo () w Javie
Wiemy, że interfejs java.lang.Comparable udostępnia metodę „compareTo ()”, za pomocą której możemy sortować obiekty w naturalnym porządku, takim jak porządek leksykalny dla obiektów typu String, porządek numeryczny dla liczb całkowitych itp.
Aby zaimplementować sortowanie w obiektach lub kolekcjach zdefiniowanych przez użytkownika, musimy przesłonić metodę compareTo (), aby posortować elementy kolekcji lub obiekty zdefiniowane przez użytkownika.
Co więc robi metoda compareTo ()?
Metoda compareTo () musi zwracać wartość dodatnią, jeśli bieżący obiekt jest większy niż przekazany obiekt w kolejności, a ujemna wartość bieżącego obiektu jest mniejsza niż przekazany obiekt. Jeśli oba obiekty są równe, metoda compareTo () zwróci zero.
Inną kwestią, na którą należy zwrócić uwagę, jest to, że metody equals () i compareTo () powinny zachowywać się spójnie. Oznacza to, że jeśli metoda compareTo () zwraca, że dwa obiekty są równe (zwraca zero), to również powinniśmy otrzymać ten sam wynik z metody equals ().
Zaimplementujmy program w języku Java, który zastępuje metodę compareTo (). W tym programie używamy klasy Color, która ma dwie prywatne zmienne, tj. Nazwę i identyfikator. Powiązaliśmy „id” z każdym kolorem i zastąpimy metodę compare (), aby uporządkować kolory zgodnie z 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() + ' , '); }
Wynik:
W powyższym wyjściu najpierw wyświetlamy listę kolorów, a następnie posortowaną listę kolorów. W programie nadpisaliśmy metody compareTo () i compare ().
Zastąp metodę toString () w języku Java
Metoda „toString ()” zwraca reprezentację String obiektu w języku Java. Ale kiedy mamy obiekty zdefiniowane przez użytkownika, ta metoda może zachowywać się inaczej.
Na przykład,rozważ następujący program.
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); } }
Wynik:
Jak pokazano w tym programie, wyświetlamy obiekt klasy Complex, który zdefiniowaliśmy wcześniej. Jednak pokazane dane wyjściowe nie są zawartością, ale są raczej tajemnicze.
Dane wyjściowe zawierają nazwę klasy Complex, po której następuje znak „@”, a następnie hashCode obiektu. Jest to domyślne wyjście drukowane przez metodę toString () klasy Object.
Jeśli chcemy uzyskać poprawne wyjście, musimy przesłonić metodę toString () w naszej aplikacji.
Poniższy program w języku Java pokazuje, jak przesłonić metodę toString () w celu wydrukowania zawartości obiektu 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); } }
Wynik:
Powyższy program pokazuje, że metoda toString () jest nadpisywana w celu zwrócenia zawartości obiektu Complex w podanym formacie (real + i * imaginary).
Generalnie, gdy chcemy wyświetlić obiekt klasy za pomocą print () lub println (), zawsze zaleca się przesłonięcie metody toString (), aby uzyskać właściwe wyjście.
Często Zadawane Pytania
Pytanie 1) Po co używać .equals zamiast == Java?
Odpowiedź: Używamy „==” do porównywania typów pierwotnych, takich jak int, char, boolean itp. Używamy equals () do porównywania obiektów (predefiniowanych lub zdefiniowanych przez użytkownika). Zwykle nadpisujemy metodę equals (), aby porównać dwa obiekty, a wartość zwracana przez equals () zależy od nadpisanego kodu.
P # 2) Do czego służy hashCode () i equals ()?
Odpowiedź: W Javie metoda equals () służy do porównywania równości dwóch obiektów. Metoda hashCode () zwraca hashCode obiektu. Chociaż metoda equals () jest używana z większością obiektów do testowania ich równości, hashCode jest najczęściej używany w kolekcjach skrótów, takich jak HashTable, HashMap, HashSet itp.
P # 3) Czy możemy zmienić listę argumentów zastąpionej metody?
Odpowiedź: Nie. Kiedy nadpisujemy metodę, zachowujemy podpis metody lub prototyp tej samej metody również w podklasie. Nie możemy więc zmienić liczby parametrów w nadpisanej metodzie.
Q # 4) Dlaczego nadpisujemy toString ()?
Odpowiedź: Gdy metoda toString () jest nadpisywana, możemy zwrócić wartości obiektu, dla którego metoda toString () została nadpisana, bez pisania zbyt dużej ilości kodu. Dzieje się tak, ponieważ kompilator java wywołuje metodę toString (), gdy drukujemy obiekt.
P # 5) Co by się stało, gdybyś nie nadpisał metody toString ()?
Odpowiedź: Jeśli nie przesłonimy metody toString (), nie uzyskamy żadnych informacji o właściwościach lub stanie obiektu. Nie będziemy wiedzieć, co faktycznie znajduje się wewnątrz obiektu. Dlatego wszystkie klasy powinny nadpisywać metodę toString ().
Dzieje się tak, ponieważ domyślna implementacja metody toString () wyświetla reprezentację typu String, ale gdy użyjemy domyślnej implementacji toString () na obiekcie, nie otrzymamy zawartości obiektu.
Wniosek
W tym samouczku omówiliśmy przesłonięcie kilku predefiniowanych metod Java, a także zobaczyliśmy, dlaczego musimy je zastąpić.
Kiedy mamy do czynienia z obiektami, domyślne implementacje metod, takich jak equals (), compareTo () i toString () mogą nie dawać poprawnych informacji. Dlatego dążymy do zastąpienia.
=> Zapoznaj się z podręcznikiem Java dla początkujących tutaj.
rekomendowane lektury
- Samouczek dotyczący ciągów Java | Metody ciągów Java z przykładami
- Wątki Java z metodami i cyklem życia
- Metoda Java String length () z przykładami
- Odwróć tablicę w Javie - 3 metody z przykładami
- Jak korzystać z metody toString w języku Java?
- Metoda Java String indexOf z przykładami kodu
- Java String zawiera () Samouczek dotyczący metody z przykładami
- Metoda Java String Split () - Jak podzielić ciąg w Javie