List list = new ArrayList();
list.add(4);
list.add(4);
list.add(234);
list.add(234);
System.out.println(list.get(0) == list.get(1));
System.out.println(list.get(2) == list.get(3)); // почему не true?
Ubuntu
30 уровень
почему не true?
Обсуждается
Комментарии (4)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Ksenia Volkova Java Developer в DXC Master
25 февраля 2020, 06:30
Потому что Integer - ссылочный тип, а ссылочные типы не сравниваются через ==.
Тебя бы скорей должно интересовать, почему в первом случае true
0
Ubuntu
25 февраля 2020, 12:23
потому что данные хешируются до 127. Но как это работает я все равно не понимаю)
меня немного настораживает, как вообще в дальнейшем сравнивать все эти оболочки.
например (list.get(2) > list.get(3)) ???????
0
hidden #598481
25 февраля 2020, 12:39полезный
Начнем с того, что ты не указал у списка дженерик <Integer>, поэтому у тебя в списке хранятся вообще не Integer, а Object.
Если указать Integer, то все работает со сравнениями:
Объясню почему и в чем отличие от "==".
Оператор сравнения "==" работает с любыми типами объектов, он сравнивает содержимое переменных (это важно). Разница только в том, что является содержимым переменной. В случае примитива - это само значение, поэтому если значения одинаковые, то и содержимое переменных одинаковое. Если это ссылочная переменная, то она содержит ссылку на участок памяти, содержащий объект. На малых значениях в переменные Integer кладутся ссылки на объекты из кэша, а не создаются новые объекты. Поэтому в случае значений из диапазона [-128; 127] "==" вернет true, т.к. содержимое переменных будет одинаковым (ссылки на один и тот же объект).
Что касается реляционных операторов >, <, >=, <=, то все проще. В отличие от "==" они не используются со ссылочными переменными, только с примитивами. Поэтому если не забыть указать дженерик <Integer>, то джава сможет выполнить автоматический каст Integer->int и сравнить полученные значения. +1
Ksenia Volkova Java Developer в DXC Master
25 февраля 2020, 12:44полезный
(list.get(2) > list.get(3)) - тут будет автораспаковка (auto-unboxing), так что проблем не возникнет.
А так - есть метод compareTo (у оберток еще и статический compare).
С кэшированием никаких сложностей нет. Набери, например, в Идее Integer.valueOf(1); , нажми Ctrl и ткни на valueOf - увидишь, как создается объект Integer.
Если коротко, то в классе Integer есть IntegerCache, который хранит массив объектов Integer в диапазоне от -128 до 127. И при вызове метода valueOf (а именно он работает при автозапаковке) программа проверяет, попадает ли число в указанный диапазон. Если да, то новый объект не создается, а возвращается объект из массива-кэша.
+1