Должно быть совершенно ясно, что кэширование имеет неприемлемое снижение производительности - дополнительный оператор if и поиск памяти каждый раз, когда вы создаете Integer.Это само по себе затмевает любую другую причину и остальную агонию в этой теме.
Что касается "правильного" ответа на ==, ФП ошибается в своем предположении о правильности.Целые числа правильно реагируют на == ожиданиями сообщества Java правильности и, конечно, определением корректности спецификации.То есть, если две ссылки указывают на один и тот же объект, они равны ==
.Если две ссылки указывают на разные объекты, они не ==
, даже если они имеют одинаковое содержимое.Таким образом, неудивительно, что new Integer(5) == new Integer(5)
оценивается как false
.
Более интересным вопросом является , почему new Object();
требуется каждый раз для создания уникального экземпляра?то есть почему new Object();
не разрешено кэшировать?Ответ - звонки wait(...)
и notify(...)
.Кэширование new Object()
s может привести к неправильной синхронизации потоков друг с другом, если они не должны этого делать.
Если бы не это, реализации Java могли бы полностью кэшировать new Object()
s с помощью синглтона.
И это должно объяснить, почему new Integer(5)
, выполненное 7 раз, необходимо для создания 7 уникальных Integer
объектов, каждый из которых содержит значение 5 (потому что Integer
расширяет Object
).
Вторичный, менее важный материал: Одна из проблем в этой, в остальном, хорошей схеме, связана с функцией автобоксирования и автопоставки.Без функции вы не могли бы сделать сравнения, такие как new Integer(5) == 5
.Чтобы включить их, Java распаковывает объект (и не блокирует примитив).Поэтому new Integer(5) == 5
преобразуется в: new Integer(5).intValue() == 5
(и не new Integer(5) == new Integer(5)
.
Последнее, что нужно понять, это то, что автобокс n
равен , а не сделано new Integer(n)
. Это делается внутренне путем вызова Integer.valueOf(n)
.
Если вы думаете, что понимаете и хотите проверить себя, прогнозируйте выход следующей программы:
public class Foo {
public static void main (String[] args) {
System.out.println(Integer.valueOf(5000) == Integer.valueOf(5000));
System.out.println(Integer.valueOf(5000) == new Integer(5000));
System.out.println(Integer.valueOf(5000) == 5000);
System.out.println(new Integer(5000) == Integer.valueOf(5000));
System.out.println(new Integer(5000) == new Integer(5000));
System.out.println(new Integer(5000) == 5000);
System.out.println(5000 == Integer.valueOf(5000));
System.out.println(5000 == new Integer(5000));
System.out.println(5000 == 5000);
System.out.println("=====");
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(5) == new Integer(5));
System.out.println(Integer.valueOf(5) == 5);
System.out.println(new Integer(5) == Integer.valueOf(5));
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(5) == 5);
System.out.println(5 == Integer.valueOf(5));
System.out.println(5 == new Integer(5));
System.out.println(5 == 5);
System.out.println("=====");
test(5000, 5000);
test(5, 5);
}
public static void test (Integer a, Integer b) {
System.out.println(a == b);
}
}
Для дополнительного кредита также прогнозируйте вывод, если все ==
будут изменены на .equals(...)
Обновление: Благодаря комментарию от пользователя @sactiw: "диапазон кэша по умолчанию равенОт -128 до 127 и Java 1.6 и выше вы можете сбросить верхнее значение> = 127, передав -XX: AutoBoxCacheMax = из командной строки "