TL; DR
Java кешує в коробках цілі екземпляри від -128
до 127
. Оскільки ви використовуєте ==
для порівняння посилань на об'єкти замість значень , відповідають лише кешовані об'єкти. Або працюйте з long
непоміченими примітивними значеннями або використовуйте .equals()
для порівняння Long
об'єктів.
Довга (призначена для каламбуру) версія
Чому існує проблема порівняння змінної Long зі значенням, що перевищує 127? Якщо тип даних вищевказаної змінної є примітивним (довгим), то код працює для всіх значень.
Java кешує об'єкти об'єктів Integer з діапазону від -128 до 127 . Це сказав:
- Якщо встановити значення N Long змінних
127
( кешоване ), один і той же екземпляр об'єкта буде вказуватися всіма посиланнями. (N змінних, 1 примірник)
- Якщо ви встановите на N Long змінних значення
128
( не кешоване ), у вас буде об’єкт об'єкта, вказаний кожним посиланням. (N змінних, N екземплярів)
Ось чому це:
Long val1 = 127L;
Long val2 = 127L;
System.out.println(val1 == val2);
Long val3 = 128L;
Long val4 = 128L;
System.out.println(val3 == val4);
Виводи це:
справжнє
хибне
Для значення 127L , оскільки обидва посилання (val1 і val2) вказують на один і той же екземпляр об'єкта в пам'яті (кешовано), воно повертається true
.
З іншого боку, для значення 128 , оскільки в пам’яті не існує жодного примірника для кешованого пам’яті, створюється новий для будь-яких нових присвоєнь для значень у вікні, в результаті чого виникають два різні екземпляри (вказані val3 та val4) і повертаються false
на порівняння між ними.
Це відбувається лише тому, що ви порівнюєте з оператором дві Long
посилання на об'єкти , а не long
примітивні значення ==
. Якби не цей механізм кешу, ці порівняння завжди були б невдалі, тому справжньою проблемою тут є порівняння значень коробки з ==
оператором.
Зміна цих змінних на примітивні long
типи запобіжить цьому, але якщо вам потрібно буде зберігати код за допомогою Long
об'єктів, ви можете сміливо робити ці порівняння з наступними підходами:
System.out.println(val3.equals(val4)); // true
System.out.println(val3.longValue() == val4.longValue()); // true
System.out.println((long)val3 == (long)val4); // true
(Правильна нульова перевірка необхідна навіть для кастингів)
IMO , завжди корисно дотримуватися методів .equals () при роботі з об'єктами порівнянь.
Довідкові посилання:
.longValue()
.