Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
Сколько объектов создается в результате операторов в приведенном выше примере кода и почему? Есть ли IDE, в котором мы можем видеть, сколько объектов создано (возможно, в режиме отладки)?
Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
Сколько объектов создается в результате операторов в приведенном выше примере кода и почему? Есть ли IDE, в котором мы можем видеть, сколько объектов создано (возможно, в режиме отладки)?
Ответ, на удивление, равен нулю.
Все Integer
от -128 до +127 предварительно вычисляются JVM.
Ваш код создает ссылки на эти существующие объекты.
Строго правильный ответ заключается в том, что количество созданных объектов Integer
неопределенно. Это может быть от 0 до 3 или 256 1 или даже больше 2 в зависимости от
int
перед ним 4.Значения Integer
для -128 до 127 не обязательно должны быть предварительно вычислены. Фактически, JLS 5.1.7, в котором указано, что Бокс конвертирует это:
Если значение p, помещенное в ячейку, является целым литералом типа int между -128 и 127 включительно (§3.10.1)... тогда пусть a и b - результаты любых двух бокс-преобразований p. Всегда бывает, что a == b.
Следует отметить две вещи:
Даже javadoc для Integer.valueof(int)
не указывает, что результаты кэшируются с нетерпением.
Если мы рассмотрим исходный код Java SE для java.lang.Integer
из Java с 6 по 8, ясно, что текущая стратегия реализации Java SE заключается в прекомпутете значения. Однако по разным причинам (см. Выше) все еще недостаточно, чтобы позволить нам дать определенный ответ на вопрос "сколько объектов".
1 - Это может быть 256, если выполнение вышеуказанного кода запускает инициализацию класса для Integer
в версии Java, где кеш с нетерпением инициализируется во время инициализации класса.
2 - Это может быть даже больше, если кеш больше, чем требуется спецификация JVM. Размер кеша может быть увеличен с помощью опции JVM в некоторых версиях Java.
3 - Помимо общего подхода платформы к внедрению бокса, компилятор мог заметить, что некоторые или все вычисления могут быть выполнены во время компиляции или полностью оптимизированы.
4 - такой код может вызвать либо ленивую, либо желаемую инициализацию цельного кеша.
Прежде всего: ответ, который вы ищете, это 0
, как уже упоминалось ранее.
Но отпустите немного глубже. Как сказал Стивен, это зависит от времени его исполнения. Поскольку кеш фактически инициализирован.
Если вы посмотрите на документацию java.lang.Integer.IntegerCache:
Кэш инициализируется при первом использовании.
Это означает, что если вы впервые вызываете любое целое число, которое вы на самом деле создаете:
Во второй раз вы вызываете их, вы создаете 0 объектов.
Все становится более забавным, когда вы делаете цифры немного выше. Например. в следующем примере:
Integer i = 1500;
Допустимыми параметрами являются: 0, 1 или любое число от 1629 до 2147483776 (на этот раз только подсчет созданных Целочисленных значений. Зачем? Ответ приведен в следующем предложении определения Integer-Cache:
Размер кеша может управляться с помощью опции -XX: AutoBoxCacheMax =.
Таким образом, вы действительно можете изменить размер кэша, который был реализован.
Это означает, что вы можете связаться с вышеприведенной строкой:
Имейте в виду: Это гарантируется только в Oracle/Open JDK (я проверил версии 7 и 8)
Как вы можете видеть, совершенно правильный ответ получить не так-то просто. Но просто сказать 0
сделает людей счастливыми.
PS: использование параметра menthoned может сделать следующее утверждение истинным: Integer.valueOf(1500) == 1500
Компилятор распаковывает объекты Integer
в int
для выполнения арифметики с ними, вызывая intValue()
, и он вызывает Integer.valueOf
, чтобы вставить теги int
, когда они назначены переменным Integer
, поэтому ваш пример эквивалентен:
Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());
Назначение j = i;
- это полностью нормальное назначение ссылки на объект, которое не создает новых объектов. Он не боксирует или не распаковывает, и не нужно, поскольку объекты Integer
неизменяемы.
Метод valueOf
позволяет кэшировать объекты и каждый раз возвращать один и тот же экземпляр для определенного числа. Требуется кэшировать ints -128 до +127. Для вашего стартового номера i = 3
все числа малы и гарантированно будут кэшироваться, поэтому количество объектов, которые необходимо создать, 0. Строго говоря, valueOf
разрешено кэшировать экземпляры лениво, а не иметь их все предварительно сгенерированные, поэтому пример может все же создавать объекты в первый раз, но если код многократно запускается во время программы, количество объектов, созданных каждый раз на средние подходы 0.
Что делать, если вы начинаете с большего числа, чьи экземпляры не будут кэшироваться (например, i = 300
)? Затем каждый вызов valueOf
должен создать один новый объект Integer
, а общее количество объектов, созданных каждый раз, 3.
(Или, может быть, это все равно ноль или, может быть, миллионы. Помните, что компиляторам и виртуальным машинам разрешено переписывать код по причинам производительности или реализации, если его поведение не изменилось иначе. Таким образом, он мог бы удалить вышеуказанный код полностью, если вы не используете результат. Или, если вы попытаетесь напечатать j
, он может понять, что j
всегда будет иметь такое же постоянное значение после вышеописанного фрагмента и, таким образом, выполнить всю арифметику во время компиляции, и напечатать постоянное значение. Фактический объем работы, выполняемой за кулисами для запуска вашего кода, всегда является детальностью реализации.)
Вы можете отладить метод Integer.valueOf(int i), чтобы узнать его самостоятельно. Этот метод вызывается процессом автобоксинга компилятором.