overriding predefined methods java
Цей підручник пояснює, як замінити заздалегідь визначені методи, такі як equals (), hashCode (), compareTo () тощо в Java, з прикладами:
У нашому попередньому уроці ми обговорювали поліморфізм виконання в Java. Поліморфізм виконання під час виконання в Java реалізований з використанням методу, що перевизначає. Перевизначення методу передбачає перевизначення методу батьківського класу в підкласі.
Java має різні заздалегідь визначені методи, такі як equals (), hashCode (), compareTo (), toString () тощо, які зазвичай використовуються для загальних об'єктів, незалежно від того, до якого класу вони належать. Але щоб ці методи працювали для всіх об’єктів, нам потрібно замінити ці методи або перевизначити їх реалізації, щоб вони могли працювати з даними, які ми хочемо.
=> Завітайте сюди, щоб вивчити Java з нуля.
У цьому підручнику ми обговоримо заміщення всіх цих методів разом із наслідками, якщо ми не замінимо ці методи.
Що ви дізнаєтесь:
- Перевизначення методів equals () та hashCode () у Java
- Заміна статичного методу в Java
- Перевизначення compareTo () в Java
- Перевизначити метод toString () у Java
- Часті запитання
- Висновок
- Рекомендована література
Перевизначення методів equals () та hashCode () у Java
Ми використовуємо метод equals () у Java для порівняння двох об’єктів. Цей метод повертає true, коли об'єкти рівні, і false, коли не рівні.
Для порівняння рівності двох об’єктів використовують два способи.
# 1) Неглибоке порівняння
Неглибоке порівняння - це реалізація за замовчуванням для методу equals (), визначеного в класі “java.lang.Object”. Як частина цієї реалізації, метод equals () перевірить, чи мають два об'єкти, що порівнюються, посилання, що посилаються на один і той же об'єкт.
Це означає, що якщо obj1 та obj2 є двома об'єктами, то реалізація за замовчуванням методу equals () (неглибоке порівняння) перевірятиме лише, чи посилання на obj1 та obj2 походять від одного і того ж об'єкта.
При неглибокому порівнянні не порівнюється вміст даних.
# 2) Глибоке порівняння
У глибокому порівнянні ми порівнюємо члени даних кожного об'єкта, тобто об'єкти порівнюються відносно стану. Отже, ми порівнюємо об’єкти на глибокому рівні, включаючи їх вміст.
Для порівняння об'єктів за допомогою глибокого порівняння ми, як правило, замінюємо метод equals ().
Тепер розглянемо наступну програму 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 '); } } }
Вихід:
Якщо ми бачимо результати вищезазначеної програми, це означає, що об’єкти не рівні, навіть незважаючи на те, що вміст двох об’єктів однаковий. Це пов’язано з тим, що, коли перевіряється рівність, визначається, чи посилаються два об’єкти c1 і c2 на один об’єкт.
Як видно в програмі c1 і c2 - це два різні об'єкти, тому вони є різними посиланнями, і, таким чином, випливає так.
Тепер давайте створимо третє посилання c3 і прирівняємо його до c1 наступним чином:
Комплекс c3 = c1;
У цьому випадку c3 і c1 посилатимуться на один і той же об'єкт, а отже (c3 == c1) повертатиме true.
Те, що зробила вищевказана програма, - це неглибоке порівняння. То як ми можемо перевірити, чи два об’єкти однакові за змістом?
найкраща програма для відкриття файлів xml
Тут ми йдемо на глибоке порівняння, і для цього ми замінюємо метод equals ().
Наступна програма показує перевизначення методу equals (). Ми використовуємо той самий комплексний клас.
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 '); } } }
Вихід:
Тепер, коли ми маємо метод overridden equals (), коли ми порівнюємо два об'єкти, результат показує, що два об'єкти рівні, оскільки їх вміст однаковий. Зверніть увагу на перевизначений метод equals (). Тут ми перевіряємо, чи мають обидва об’єкти однакові посилання. Якщо ні, то ми індивідуально перевіряємо вміст цих об’єктів.
У Java, коли ми замінюємо метод equals (), доцільно також замінити метод hashCode (). Це тому, що якщо ми не замінюємо метод hashCode (), тоді кожен об’єкт може мати різний hashCode.
Це може не заважати загальним об'єктам, але деякі колекції на основі хешів, такі як HashTable, HashSet та HashMap, можуть не працювати належним чином.
Наступна програма показує перевизначені методи equals () та 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()); } } }
Вихід:
У цій програмі ми використовуємо hashMap. Ми перевизначили і методи equals (), і hashCode (). Отже, коли ми говоримо map.put (e1, “C ++”), він хешує до певного сегмента. Далі ми називаємо map.put (e2, “Python”). Цього разу він буде хеш до того ж сегмента і замінить попереднє значення. Це тому, що ми перевизначили метод hashCode ().
Заміна статичного методу в Java
Чи можемо ми замінити статичний метод у Java?
Що стосується перевизначення статичного методу в Java, пряма відповідь на це запитання - Ні, ми не можемо замінити статичний метод.
Статичний метод викликається за допомогою самого імені класу. Нам не потрібен об’єкт для виклику статичного методу. Отже, навіть якщо ми оголосимо метод з однаковим прототипом у підкласі, ми не можемо назвати його перевизначенням. Натомість ми просто приховуємо визначення батьківського класу статичного методу.
Наступна програма Java показує статичний метод та нестатичний метод у системі успадкування разом із їх поведінкою під час виконання.
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(); } }
Вихід:
З виходу програми можна зробити наступний висновок.
- Виклик статичного методу завжди здійснюється на основі типу посилання. Отже, коли ми зателефонували new_obj. display () у вищезазначеній програмі, оскільки посилання new_obj відноситься до типу класу Parent, викликається метод display () класу Parent.
- З іншого боку, нестатичні методи викликаються на основі вмісту посилального об'єкта, з яким викликається метод. Отже, у наведеній вище програмі метод new_obj.print () викликає метод print () дочірнього класу, оскільки вміст new_obj є об'єктом дочірнього класу.
Це пояснює результати програми вище, і нам слід пам’ятати наступні моменти, маючи справу зі статичними методами в системі ООП.
- Статичний метод не може приховати нестатичний метод екземпляра, а нестатичний метод екземпляра не може замінити статичний метод.
- Ми можемо перевантажити методи з батьківського класу в підкласі, але вони ні перевизначають, ні приховують методи батьківського класу, скоріше це нові методи в підкласі.
Перевизначення compareTo () в Java
Ми знаємо, що інтерфейс java.lang.Comparable забезпечує метод ‘compareTo ()’, за допомогою якого ми можемо сортувати об’єкти в природному порядку, як лексичний порядок для об’єктів String, числовий порядок для цілих чисел тощо.
Для реалізації сортування в визначених користувачем об'єктах або колекціях нам потрібно замінити метод compareTo () для сортування елементів колекції або визначених користувачем об'єктів.
То що робить метод compareTo ()?
Метод compareTo () повинен повертати позитивне значення, якщо поточний об'єкт більше, ніж переданий об'єкт в порядку, а негативне значення поточного об'єкта менше, ніж переданий об'єкт. Якщо обидва об'єкти рівні, тоді метод compareTo () поверне нуль.
Ще один момент, на який слід звернути увагу, полягає в тому, що метод equals () і compareTo () повинен поводитися послідовно один з одним. Це означає, що якщо метод compareTo () повертає, що два об'єкти рівні (повертає нуль), тоді ми повинні мати однаковий результат і з методу equals ().
Давайте реалізуємо програму Java, яка замінює метод compareTo (). У цій програмі ми використовуємо клас Color, який має дві приватні змінні, тобто name та id. Ми пов’язали ‘id’ з кожним кольором, і ми замінимо метод compare (), щоб розташувати кольори відповідно до 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() + ' , '); }
Вихід:
У наведеному вище результаті ми спочатку відображаємо список кольорів, а потім відсортований список кольорів. У програмі ми перевизначили методи compareTo () та compare ().
Перевизначити метод toString () у Java
Метод ‘toString ()’ повертає подання String об’єкта в Java. Але коли ми маємо визначені користувачем об’єкти, тоді цей метод може поводитися по-різному.
Наприклад,розглянемо наступну програму.
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); } }
Вихід:
Як показано в цій програмі, ми відображаємо об'єкт класу Complex, який ми визначили раніше. Однак показаний результат - не вміст, а досить загадковий.
На виході відображається назва класу Complex, за якою слідує символ „@“, а потім hashCode об’єкта. Це вихід за замовчуванням, надрукований методом toString () класу Object.
Якщо ми хочемо належного виводу, тоді нам потрібно замінити метод toString () у нашому додатку.
Наступна програма Java показує, як замінити метод toString () для друку вмісту об'єкта 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); } }
Вихід:
Вищенаведена програма показує, що метод toString () замінено, щоб повернути вміст Складного об'єкта у заданому форматі (реальний + i * уявний).
Загалом, коли ми хочемо відобразити об’єкт класу за допомогою print () або println (), то завжди доцільно замінити метод toString (), щоб ми отримали належний результат.
Часті запитання
Q # 1) Навіщо використовувати .equals замість == Java?
Відповідь: Ми використовуємо ‘==’ для порівняння примітивних типів, таких як int, char, boolean тощо. Для порівняння об’єктів (заздалегідь визначених або визначених користувачем) використовуємо equals (). Зазвичай ми замінюємо метод equals () для порівняння двох об’єктів, а повернене значення equals () залежить від заміненого коду.
Q # 2) Для чого використовується hashCode () та equals ()?
Відповідь: У Java метод equals () використовується для порівняння рівності двох об’єктів. Метод hashCode () повертає hashCode об'єкта. Хоча метод equals () використовується з більшістю об'єктів для перевірки їх рівності, hashCode в основному використовується в хеш-колекціях, таких як HashTable, HashMap, HashSet тощо.
Q # 3) Чи можемо ми змінити список аргументів перевизначеного методу?
Відповідь: Ні. Коли ми замінюємо метод, ми також зберігаємо однакові підпис методу або прототип методу в підкласі. Отже, ми не можемо змінити кількість параметрів у перевизначеному методі.
Q # 4) Чому ми замінюємо toString ()?
Відповідь: Коли метод toString () замінено, ми можемо повернути значення об'єкта, для якого метод toString () замінений, не записуючи занадто багато коду. Це тому, що компілятор Java викликає метод toString (), коли ми друкуємо об’єкт.
Q # 5) Що станеться, якщо ви не заміните метод toString ()?
Відповідь: Якщо ми не перевизначимо метод toString (), ми не отримаємо жодної інформації про властивості або стан об’єкта. Ми не будемо знати, що насправді знаходиться всередині об’єкта. Отже, усі класи повинні замінити метод toString ().
Це пояснюється тим, що реалізація за замовчуванням методу toString () відображає представлення String, але коли ми використовуємо реалізацію toString () за замовчуванням на об’єкті, то ми не отримаємо вміст об’єкта.
Висновок
У цьому підручнику ми обговорили перевизначення декількох заздалегідь визначених методів Java, а також побачили, чому нам потрібно їх замінити.
Коли ми маємо справу з об’єктами, реалізації методів за замовчуванням, таких як equals (), compareTo () та toString (), можуть не давати правильної інформації. Отже, ми переходимо до перевизначення.
=> Подивіться тут посібник для початківців Java.
Рекомендована література
- Підручник із рядків Java | Рядові методи Java на прикладах
- Потоки Java з методами та життєвим циклом
- Довжина рядка Java () Метод із прикладами
- Зворотній масив у Java - 3 методи з прикладами
- Як використовувати метод Java toString?
- Індекс рядка Java методу з прикладами коду
- Рядок Java містить () Підручник із методів із прикладами
- Метод розділення рядка Java () - Як розділити рядок у Java