Завжди використовуйте equals() для порівняння об’єктів типу Integer у Java

Порівняння об'єктів типу Integer за допомогою == може дати непослідовні результати. Ось посібник, щоб зрозуміти Integer; equals() проти ==, і як правильно їх використовувати

pic

Integer є обгорткою для примітивного типу int у Java.

Що таке класи-обгортки? Класи-обгортки дають можливість використовувати примітивні типи даних (int, boolean тощо) як об'єкти. Це як упакувати простий подарунок (примітивний тип даних, як-от int) у розкішну декоративну обгортку (наприклад, Integer), щоб його можна було використовувати в більш гнучкий і потужний спосіб.

Підожди, у чому різниця між equals() і ==?

Уявімо, що у вас є дві копії однієї й тієї ж книги.

  • У Java оператор == перевіряє, чи є два об'єкти (у цьому випадку, дві книги) одним і тим самим об'єктом. В даному випадку це не так; дві книги — це окремі фізичні копії.
  • З іншого боку, метод equals() перевіряє, чи є вміст/значення двох об'єктів однаковими. Тут так, вміст двох книг ідентичний. Кожна сторінка в одній книзі така ж, як відповідна сторінка в іншій.

Але чому == працює в деяких випадках?

Давайте розглянемо наступний приклад:

public class IntegerExample {  
 public static void main(String[] args) {  
 //Випадок 1  
 Integer x = 100;   
 Integer y = 100;   
 System.out.println(x == y); // true  

 //Випадок 2  
 Integer m = 200;   
 Integer n = 200;   
 System.out.println(m == n); // false  
 }  
}

Це плутає, правда? Чому один випадок спрацював, а інший — ні?

Ось чому: Java використовує кешування для оптимізації продуктивності та ефективності пам'яті. Для діапазону від -128 до 127 Java повторно використовує об'єкти за посиланням.

Що це взагалі означає??? Дозвольте пояснити:

Коли ви створюєте об'єкт, Java виділяє йому місце. Для діапазону від -128 до 127 об'єкт створюється в кеш-області хіпу, і якщо кілька змінних ініціалізовано однаковим значенням, замість створення кількох екземплярів, Java вказує всі ці змінні на одне й те саме місце. Але для значень поза цим діапазоном для кожної нової змінної виділяється нове місце/пам'ять. Використання одного й того самого екземпляра заощаджує пам'ять.

pic

Ось чому в випадку 1 ми отримуємо true, тому що == порівнює адреси об'єктів, і в даному випадку обидва значення x і y насправді вказують на один і той самий об'єкт. Але це не так для m і n.

Тому завжди використовуйте equals(), тому що він завжди порівнюватиме вміст/значення, а не посилання.`

Покладання на == для порівняння об'єктів може призвести до несподіваних результатів в залежності від порівнюваних значень. Використання equals() гарантує, що ваш код порівнюватиме фактичні значення, а не посилання в пам'яті.

Заключні зауваження та деякі поширені запитання, які можуть виникнути

  • Це кешування для Integer працює тільки з автоматичним упаковуванням (auto-boxing). Об'єкти Integer не кешуються, коли вони створюються за допомогою конструктора, тобто:
    Integer x = new Integer(100)
  • Що таке автоматичне упаковування (auto-boxing)? Це автоматичне перетворення між примітивними типами даних і їх відповідними класами-обгортками.
  • Кешування застосовується й до інших класів-обгорток, таких як Character (ASCII 0 до 127),
    Boolean (true/false),
    Byte, Short, Long (-128 до 127).
  • Чи можна збільшити ліміт кешування? Так, це можна налаштувати за допомогою опції JVM
    -XX:AutoBoxCacheMax.
  • Що відбувається з змінною y у пам'яті, якщо я оновлю змінну x у наведеному вище прикладі на x = 150?
    Integer є незмінним (immutable), тому Java автоматично створює новий екземпляр для змінної, коли виконуються операції для зміни її значення. Тому тут x тепер буде вказувати на новий екземпляр зі значенням 150, а y вказуватиме на те саме старе місце зі значенням 100.

Перекладено з: Always use equals() to compare Integer Objects in Java

Leave a Reply

Your email address will not be published. Required fields are marked *