Примерно с такой фразы началась техническая часть одного из моих собеседований. После очередной затяжки электронной сигареты собеседующий прислал ссылку.
В целом, крупный российский биржевой холдинг может себе позволить “лайвкодинг в блокноте”, о котором ведется множество
дебатов в последнее время.
А вот человек, покуривающий на фоне интернет-мема “Них** не понял, но очень интересно.”, и до этого момента вызывал
сугубо желание завершить встречу досрочно.
Но работая в компании, которая всем сердцем полюбила
аутстаффинг, приходится в итоге действовать немного
иначе.
Что же, отбросим лирику и перейдем к сути статьи. Как точно выглядел код для “расскажите, какой тут будет вывод” я уже не помню, но смысл был примерно следующий:
1Integer a = new Integer(127);
2Integer b = 127;
3Integer c = 127;
4
5Integer d = new Integer(128);
6Integer e = 128;
7Integer f = 128;
8
9System.out.println(a == b);
10System.out.println(a.equals(b));
11
12System.out.println(b == c);
13System.out.println(b.equals(c));
14
15System.out.println(d == e);
16System.out.println(d.equals(e));
17
18System.out.println(e == f);
19System.out.println(e.equals(f));
Про упаковку (boxing) и распаковку (unboxing) между примитивными типами и эквивалентными классами-обертками, я конечно знаю, как и про кеширование определенного диапазона значений. Но вот не припомню, даже за последние 5 лет разработки исключительно на Java, о каком-либо дефекте из-за попытки сравнения Integer через оператор. А вы встречали такие проблемы на практике?
После указания всей имеющейся вереницы true/false, я озвучил, что не на сто процентов уверен по части числа 128, но, вроде, кеширование заканчивается на 127. На что собеседующий, с посылом о необходимости знать такие догмы, написал в блокноте [-128; 127].
Если заглянуть в спецификацию языка , то там можно найти отдельный раздел 5.1.7 “Boxing Conversion” , где будет упомянут такой диапазон кеширования для всех целочисленных типов. Но и обязательные требования, что выходить за рамки данного диапазона недопустимо, отсутствуют. Наоборот там прямо указывается:
Less memory-limited implementations might, for example, cache all char and short values, as well as int and long values in the range of -32K to +32K.
И вот именно в части Integer окончание диапазона кеширования на 127 уже давно не является догмой. Даже если говорить исключительно про OpenJDK и HotSpot JVM, которые принято считать основными реализациями.
Изменить результат сравнения e и f для значения 128 можно путем задания одной опции JVM :
-Djava.lang.Integer.IntegerCache.high=128
При этом нижняя граница -128 остается зафиксированной, и не предусмотренно установки верхней границы кеширования менее 127.
Также существует второй вариант указания опции через -XX:AutoBoxCacheMax
, которая будет иметь приоритет над первой.
Автоматические упаковка и распаковка появились еще в 5 версии Java. А вот возможность изменения верхней границы кеширования Integer в 1.6.0_14, если верить журналам изменений
Так что, в попытке исключить “рассказывание уже давно написанных ответов”, главное не забывать перепроверить актуальность уникальных задач из 2004 года.
P.S. Начиная с 9 версии конструкторы класса Integer помечены @Deprecated.
Источник изображения в заголовке Unsplash. Автор Steve Johnson .