Создать новый объект Integer, содержащий значение 1?

Чтобы создать новый объект 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

Метод 4: Integer p = Integer.valueOf(1);

Jacob G. 18.04.2018 18:39

Немного предыстории: если вы используете Integer.valueOf(int value);, то класс Integer может возвращать ранее созданные объекты Integer с таким же значением (это работает, поскольку Integer неизменяемы).

Turing85 18.04.2018 18:41

@JacobG. Зачем мне использовать метод valueOf при создании объекта в первый раз, и не могли бы вы также объяснить, почему это лучший метод, чем любой из упомянутых способов. Спасибо

noogler 18.04.2018 18:44

@noogler Проверить Джонатан ответ

Jacob G. 18.04.2018 18:46

@Jacob Хотя ваш метод определенно верен, я не вижу причин предпочитать метод 4 методу 2. Он дает тот же результат из-за автобокса.

Dorian Gray 18.04.2018 19:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
9
5
13 170
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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 18.04.2018 19:01

@lexicore, хотя это правда, какая причина может быть для создания нового объекта Integer, если другой объект с таким же значением уже существует? Integer неизменны.

Turing85 18.04.2018 19:02

@ Turing85 Практически - наверное, нет. Для вопроса викторины это может быть важно.

lexicore 18.04.2018 19:09

@lexicore ну ... странная викторина, я бы сказал;) тем более, что оба C'tor устарели (что является самым близким Oracle, который когда-либо доберется до "удаления" какого-либо общедоступного метода или переключения его на private) =).

Turing85 18.04.2018 19:11

@ Turing85 Не то чтобы меня удивляли странные викторины. Но мне этот вопрос действительно кажется вопросом викторины.

lexicore 18.04.2018 19:15
Ответ принят как подходящий

Вы пропустили предполагаемое решение:

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.

Integer#Integer(int value):

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. [...]

Integer#Integer(String s):

Deprecated. It is rarely appropriate to use this constructor. Use parseInt(String) to convert a string to a int primitive, or use valueOf(String) to convert a string to an Integer object. [...]

И для полноты картины вот часть для Integer.valueOf(int i):

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.


РЕДАКТИРОВАТЬ 1: Спасибо @VGR упомянув, что

Integer p = 1;

эквивалентен

Integer p = Integer.valueOf(1);

Это, однако, верно только для значений int между -128 и 127. Поведение определяется в JLS §5.1.7:

[...] If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.


Обновлено еще раз: Спасибо @DorianGray, который обратил мое внимание на следующее.

Версия javac, которую я использую (9.0.4), не входит в JLS, но компилирует бокс до Integer.valueOf(...);, как показано в этот ответ Адама Розенфилда.

Стоит отметить, что Integer p = 1; функционально идентичен этому.

VGR 18.04.2018 19:12

@VGR добавлен. Спасибо за подмигивание =)

Turing85 18.04.2018 19:18

На самом деле Integer p = 1 всегда эквивалентен Integer p = Integer.valueOf(1), это просто более короткое обозначение.

Dorian Gray 18.04.2018 19:24

Я все еще вижу ссылку на диапазон int.

Dorian Gray 18.04.2018 19:27

@TobiasWeimer Да, не все значения int кэшируются. Только те, которые находятся между -128 и 127, гарантированно будут исправлены (как указано в документации и как определено в JLS). Или я неправильно понимаю ваше утверждение?

Turing85 18.04.2018 19:30

Я говорил о том, что Integer p = 1 всегда оценивается как Integer p = Integer.valueOf(1) - так реализован автобокс. Они оба используют один и тот же кеш и идентичны по поведению.

Dorian Gray 18.04.2018 19:33

@TobiasWeimer, у вас есть какие-нибудь указания по этому поводу? Если так, я бы с радостью добавил это к своему ответу.

Turing85 18.04.2018 19:36

Что ж, интересно, это поведение не указано в опубликованной вами ссылке JLS, поэтому я должен исправить себя, что мое утверждение в целом неверно и реализация специфична для виртуальной машины. Я нашел в stackoverflow.com/questions/408661/… рассуждение по этому поводу.

Dorian Gray 18.04.2018 19:55

@TobiasWeimer Добавлен. Спасибо за ссылку!

Turing85 18.04.2018 20:03

Другие вопросы по теме