Чтобы создать новый объект Integer, который содержит значение в java 1, какой из следующих вариантов является правильным и в чем именно заключается разница в следующих методах, поскольку все они печатают значение?
Способ 1:
Integer p = new Integer(1);
Способ 2:
Integer p = 1;
Способ 3:
Integer p = new Integer("1");
Используя третий метод, я получил следующее предупреждение:
Note: HelloWorld.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details
Немного предыстории: если вы используете Integer.valueOf(int value);, то класс Integer может возвращать ранее созданные объекты Integer с таким же значением (это работает, поскольку Integer неизменяемы).
@JacobG. Зачем мне использовать метод valueOf при создании объекта в первый раз, и не могли бы вы также объяснить, почему это лучший метод, чем любой из упомянутых способов. Спасибо
@noogler Проверить Джонатан ответ
@Jacob Хотя ваш метод определенно верен, я не вижу причин предпочитать метод 4 методу 2. Он дает тот же результат из-за автобокса.




Метод 4, Integer p = Integer.valueOf(1); - рекомендуемый способ. В JavaDoc говорится:
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
Если взять вопрос в том виде, в каком он написан, Integer.valueOf(1) является правильным решением нет, поскольку нет гарантированно создает, цитирую, «новый объект Integer».
@lexicore, хотя это правда, какая причина может быть для создания нового объекта Integer, если другой объект с таким же значением уже существует? Integer неизменны.
@ Turing85 Практически - наверное, нет. Для вопроса викторины это может быть важно.
@lexicore ну ... странная викторина, я бы сказал;) тем более, что оба C'tor устарели (что является самым близким Oracle, который когда-либо доберется до "удаления" какого-либо общедоступного метода или переключения его на private) =).
@ Turing85 Не то чтобы меня удивляли странные викторины. Но мне этот вопрос действительно кажется вопросом викторины.
Вы пропустили предполагаемое решение:
Integer p = Integer.valueOf(1);
Этот шаблон известен как Шаблон заводского метода. Можно спросить, в чем преимущество этого метода. К счастью, реализация класса Integer с открытым исходным кодом, так что давайте посмотрим:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Похоже, там какой-то кеш с Integer-значением. Если кто-то запрашивает Integer со значением в пределах диапазона кэша, Java не создает новый объект, а возвращает ранее созданный. Это работает, потому что Integer неизменяемы. Можно даже контролировать верхний предел кеша с помощью системного свойства java.lang.Integer.IntegerCache.high=....
И почему два других метода создания Integer выдают предупреждение? Потому что они были объявлены устаревшими с Java 9.
Deprecated. It is rarely appropriate to use this constructor. The static factory
valueOf(int)is generally a better choice, as it is likely to yield significantly better space and time performance. [...]
Deprecated. It is rarely appropriate to use this constructor. Use
parseInt(String)to convert a string to aintprimitive, or usevalueOf(String)to convert a string to anIntegerobject. [...]
И для полноты картины вот часть для Integer.valueOf(int i):
Returns an
Integerinstance representing the specifiedintvalue. If a newIntegerinstance is not required, this method should generally be used in preference to the constructorInteger(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range-128to127, inclusive, and may cache other values outside of this range.
РЕДАКТИРОВАТЬ 1: Спасибо @VGR упомянув, что
Integer p = 1;
эквивалентен
Integer p = Integer.valueOf(1);
Это, однако, верно только для значений int между -128 и 127. Поведение определяется в JLS §5.1.7:
[...] If the value
pbeing boxed is the result of evaluating a constant expression (§15.28) of typeboolean,char,short,int, orlong, and the result istrue,false, a character in the range'\u0000'to'\u007f'inclusive, or an integer in the range-128to127inclusive, then letaandbbe the results of any two boxing conversions ofp. It is always the case thata == b.
Обновлено еще раз: Спасибо @DorianGray, который обратил мое внимание на следующее.
Версия javac, которую я использую (9.0.4), не входит в JLS, но компилирует бокс до Integer.valueOf(...);, как показано в этот ответ Адама Розенфилда.
Стоит отметить, что Integer p = 1; функционально идентичен этому.
@VGR добавлен. Спасибо за подмигивание =)
На самом деле Integer p = 1 всегда эквивалентен Integer p = Integer.valueOf(1), это просто более короткое обозначение.
Я все еще вижу ссылку на диапазон int.
@TobiasWeimer Да, не все значения int кэшируются. Только те, которые находятся между -128 и 127, гарантированно будут исправлены (как указано в документации и как определено в JLS). Или я неправильно понимаю ваше утверждение?
Я говорил о том, что Integer p = 1 всегда оценивается как Integer p = Integer.valueOf(1) - так реализован автобокс. Они оба используют один и тот же кеш и идентичны по поведению.
@TobiasWeimer, у вас есть какие-нибудь указания по этому поводу? Если так, я бы с радостью добавил это к своему ответу.
Что ж, интересно, это поведение не указано в опубликованной вами ссылке JLS, поэтому я должен исправить себя, что мое утверждение в целом неверно и реализация специфична для виртуальной машины. Я нашел в stackoverflow.com/questions/408661/… рассуждение по этому поводу.
@TobiasWeimer Добавлен. Спасибо за ссылку!
Метод 4:
Integer p = Integer.valueOf(1);