Упакованное значение распаковано, а затем повторно упаковано

FindBugs выдает мне предупреждение о следующей строке, где invoiceNumber — это объект Integer:

text.append(String.format("%010d-", (invoiceNumber == null) ? 0 : invoiceNumber));

Предупреждение: «Упакованное значение распаковывается, а затем сразу же повторно упаковывается».

Теперь я думаю, что понимаю (не)бокс, но я не понимаю, как вы могли бы сделать то же самое, не получив предупреждения?

Я обнаружил, что могу избавиться от предупреждения, используя вместо этого следующий код, но он кажется более многословным:

int invNo = (invoiceNumber == null) ? 0 : invoiceNumber;
text.append(String.format("%010d-", invNo));

Может ли кто-нибудь показать мне, что такое «правильный» способ сделать вышеперечисленное?

Кстати, я просмотрел связанные вопросы и понимаю, что с ними происходит, но, похоже, это не соответствует ни одному из них.


person DuncanKinnear    schedule 17.08.2015    source источник
comment
Возможно, text.append(String.format("%010d-", (invoiceNumber == null) ? Ineger.valueOf(0) : invoiceNumber)); подойдет.   -  person Eran    schedule 17.08.2015
comment
Да, это избавляет от предупреждения, но почему это «лучше». Он создает объект Integer (который должен быть дорогим), но в этом нет необходимости.   -  person DuncanKinnear    schedule 17.08.2015
comment
В случае 0 (или любого целого числа от -128 до 127) новый экземпляр Integer не создается, поскольку экземпляр уже доступен в IntegerCache. И вы сохраняете операции распаковки и упаковки, так что это может дать вам небольшое улучшение производительности.   -  person Eran    schedule 17.08.2015
comment
На самом деле вы создаете новый Integer в своем исходном коде, а также в своем исправлении с int invNo = (invoiceNumber == null) ? 0 : invoiceNumber; (хотя предупреждение FindBugs исчезает), но с помощью решения @Eran вы не будете создавать новый Integer, а повторно используете существующий. Что ж, хотя ответ Эрана правильный (за него проголосовали), в целом вы можете просто проигнорировать это предупреждение. Очень маловероятно, что это на самом деле повредит производительности вашего приложения. Созданный дополнительный Integer очень недолговечен.   -  person Tagir Valeev    schedule 17.08.2015


Ответы (2)


Тип выражения (invoiceNumber == null) ? 0 : invoiceNumber)int. Требуется распаковка invoiceNumber в случае, если invoiceNumber не null.

С другой стороны, String.format ожидает один аргумент String, за которым следуют Object ссылки, а это означает, что ваш int немедленно снова упаковывается в Integer.

Вы можете попытаться избежать исходной распаковки, используя (invoiceNumber == null) ? Integer.valueOf(0) : invoiceNumber), что заставит это выражение возвращать Integer.

person Eran    schedule 17.08.2015
comment
Значит ли это, что мое двухстрочное «решение» в моем вопросе на самом деле менее эффективно, потому что invoiceNumber распаковывается в invNo, а затем переупаковывается в Integer для String.format? - person DuncanKinnear; 17.08.2015
comment
@DuncanKinnear, точно! - person Tagir Valeev; 17.08.2015
comment
@DuncanKinnear Я предполагаю, что ваше двухстрочное «решение» только не позволяет FindBugs обнаруживать распаковку и повторную упаковку, поэтому на самом деле оно ничего не меняет по сравнению с вашим исходным кодом. - person Eran; 17.08.2015
comment
@DuncanKinnear Нет, вторая версия имеет такую ​​​​же неэффективность (сохраните назначение одноразовой локальной переменной, которую компилятор, вероятно, оптимизирует). - person David Harkness; 17.08.2015

Попробуйте изменить (invoiceNumber == null) ? 0 : invoiceNumber на (invoiceNumber == null) ? 0 : invoiceNumber.intValue(). Я думаю, что предупреждение исходит от того, что вы снова используете Integer в «ложном» случае, а не int.

person saagarjha    schedule 17.08.2015
comment
Нет, то же предупреждение. Я попытался присвоить ложное значение (int) и все равно получил предупреждение. - person DuncanKinnear; 17.08.2015
comment
Предупреждение, когда меня нет дома… какую версию Java вы используете? - person saagarjha; 17.08.2015
comment
Вы уверены, что используете точно такой же код, включая String.format? - person DuncanKinnear; 17.08.2015
comment
Да. Какой тип text? StringBuilder? StringBuffer? - person saagarjha; 17.08.2015
comment
StringBuilder. Вероятно, не стоит продолжать, поскольку решение Эрана кажется более подходящим. Его объяснение также объяснило бы, почему intValue() не решает «проблему», поскольку полученное int все еще упаковано для использования в качестве аргумента String.format. - person DuncanKinnear; 17.08.2015