Кэш Integer — предскажите три сравнения ==
Учитывая автоупаковку и кэш Integer, определите результат каждого сравнения и объясните, почему два одинаковых на вид значения могут сравниться по-разному.
Ограничения:
- рассуждайте о тождестве ссылок (
==), а не оequals - учтите стандартный диапазон кэша
Integer
Integer a = 100, b = 100; // r1 = a == b ?
Integer c = 200, d = 200; // r2 = c == d ?
Integer e = new Integer(100), f = new Integer(100); // r3 = e == f ?
Определите r1, r2, r3 и обоснуйте каждый.
r1 равно true, r2 — false, r3 — false. Автоупаковка вызывает Integer.valueOf, который кэширует объекты для -128..127, поэтому 100 возвращает один и тот же закэшированный объект (== true), а 200 вне диапазона и упаковывается в новый объект каждый раз (== false). new Integer(100) всегда выделяет память, поэтому два вызова new никогда не ==.
- ✗Считать, что
==на боксированномIntegerвсегда сравнивает числовое значение, а не тождество ссылок - ✗Полагать, что кэш покрывает все значения, а не только
-128..127 - ✗Думать, что
new Integer(100)участвует в кэшировании, а не всегда выделяет память
- →Как можно изменить верхнюю границу кэша
Integer? - →Почему конструктор
new Integer(int)объявлен устаревшим в Java 9?
Разбор
Integer a = 100, b = 100;
System.out.println(a == b); // true — оба из кэша
Integer c = 200, d = 200;
System.out.println(c == d); // false — вне кэша, два разных объекта
Integer e = new Integer(100), f = new Integer(100);
System.out.println(e == f); // false — new всегда выделяет память
Автоупаковка литерала Integer a = 100; компилируется в Integer.valueOf(100). Метод valueOf держит кэш объектов для значений -128..127 и возвращает из него готовый экземпляр. Поэтому a и b ссылаются на один объект → == даёт true.
Значение 200 выходит за границу кэша, поэтому valueOf каждый раз создаёт новый объект → c == d равно false.
new Integer(100) обходит valueOf и всегда выделяет новый объект, поэтому e == f всегда false.
Верхнюю границу кэша можно поднять опцией -XX:AutoBoxCacheMax=<n> (или -Djava.lang.Integer.IntegerCache.high=<n>). Сравнивать значения обёрток нужно через equals, а не ==.