Распаковка Long в Java

В каком-то коде я вижу это:

private void compute(Long a, Long b, Long c) {
        long result = a-(b+c);
...

Кажется немного странным, что результат сохраняется в примитиве long вместо объекта Long, соответствующего его операндам.

Есть ли причина, по которой результат должен храниться как примитив?


person u123    schedule 31.05.2013    source источник
comment
Более серьезный вопрос заключается в том, почему Long вообще используется. Это гораздо менее эффективно.   -  person Peter Lawrey    schedule 31.05.2013
comment
Он хранится как примитив, потому что вы объявили его как примитив.   -  person enkor    schedule 31.05.2013
comment
Возможно, вы можете найти некоторые подсказки здесь ссылка   -  person PbxMan    schedule 31.05.2013
comment
@ dmiller2117 Я полагаю, он имел в виду, что читает чужой код и задается вопросом, почему этот кто-то использовал там примитивный тип.   -  person noamik    schedule 31.05.2013
comment
Также забавно, что у метода void есть локальная переменная с именем result ... но я думаю, это будет означать что-то еще: P   -  person Svend Hansen    schedule 31.05.2013
comment
Если вы когда-нибудь сделаете это самостоятельно, подумайте, может ли какой-либо из a, b и c быть null, так как вы получите не очень очевидный NullPointerException, когда автоматическая распаковка вызовет для них .longValue() в выражении.   -  person Svend Hansen    schedule 31.05.2013


Ответы (9)


Кажется немного странным, что результат сохраняется в примитиве long вместо объекта Long, соответствующего его операндам.

Нет, что "странно", так это то, что вы можете использовать операторы + и - для объектов Long. До Java 5 это было бы синтаксической ошибкой. Затем была введена автоупаковка/распаковка. В этом коде вы видите автораспаковка: операторы требуют примитивов, поэтому компилятор автоматически вставляет вызов longValue() в объекты. Затем над примитивными значениями long выполняются арифметические действия, и результатом также является long, которое можно сохранить без дальнейшего преобразования переменной.

Что касается почему код делает это, реальный вопрос заключается в том, почему кто-то может использовать тип Long вместо long. Возможные причины:

  • Значения поступают из некоторой библиотеки/API, которые предоставляют Long значений.
  • Значения хранятся в коллекциях (List, Map), которые не могут содержать примитивы.
  • Небрежность или программирование культа грузов.
  • Требуется возможность иметь null значений, например. сигнализировать о недоступных или неинициализированных данных.

Обратите внимание, что способность Long содержать null значений означает, что вычисление (или, точнее, вызовы longValue(), вставленные компилятором) могут завершиться ошибкой с NullPointerException - возможность, с которой код должен каким-то образом справиться.

person Michael Borgwardt    schedule 31.05.2013

Причина очевидна: результат объявлен примитивным.

person nakosspy    schedule 31.05.2013
comment
Это на самом деле не причина. - person Michael Borgwardt; 31.05.2013
comment
Я не понимаю, почему это не причина. Если под результатом вы понимаете объявленную переменную, то причина в этом. Если под результатом вы понимаете результат операции a-(b+c), то причина в том, что операция сложения определена для примитивов, и поэтому Long автоматически распаковываются перед добавлением. - person nakosspy; 31.05.2013

Арифметические операторы + и - определены не для коробочных типов (например, Long), а для примитивных типов (например, long).

Результат тоже длинный. См. руководство по автоматической упаковке и распаковке.

Автоупаковка этого в Long приведет к небольшому снижению производительности. Это также ненужно, потому что

  1. Мы знаем, что он будет ненулевым (если бы a, b или c были нулевыми, возникло бы исключение NullPointerException).
  2. Это будет неявно автоматически упаковываться, если мы используем его позже, когда требуется Long.
person Peter Crotty    schedule 31.05.2013

Исходя из ваших потребностей. Я имею в виду замедление.

Autoboxing и unboxing могут происходить везде, где ожидается объект и доступен примитивный тип

person Suresh Atta    schedule 31.05.2013

Обычно лучше использовать примитивы, особенно если вы уверены, что они не могут быть нулевыми. Если вы настаиваете на использовании типов в штучной упаковке, всегда тщательно думайте о том, что происходит, когда он равен нулю. Java упаковывает и распаковывает автоматически за вас, но смотреть на int и задаваться вопросом, почему вы получили исключение NullPointerException, может быть весело.

person koljaTM    schedule 31.05.2013

Начиная с Java 1.5 и далее автоупаковка и распаковка происходят неявно, когда это необходимо.

person Sumit Desai    schedule 31.05.2013

Следующая строка:

long result = a-(b+c);

... просит Java взять результат выражения, используя 3 Longs, а затем сохранить его в примитиве long. До Java 5 он жаловался на несоответствие типов, но в наши дни он просто предполагает, что вы имеете в виду то, что говорите, и автоматически выполняет преобразование из объекта в примитивный тип для вас.

Однако в этом примере, если нет какой-либо другой веской причины, не представленной здесь, в первую очередь нет абсолютно никакого смысла иметь параметры как тип объекта в штучной упаковке.

person Michael Berry    schedule 31.05.2013

Согласно javadoc

Boxing conversion converts expressions of primitive 
type to corresponding expressions of reference type. 
Specifically, the following nine conversions are called the boxing conversions:

From type boolean to type Boolean

From type byte to type Byte

From type short to type Short

From type char to type Character

From type int to type Integer

From type long to type Long

From type float to type Float

From type double to type Double

From the null type to the null type


Ideally, boxing a given primitive value p, would always yield an identical reference.     
In practice, this may not be feasible using existing implementation techniques. The  
rules above are a pragmatic compromise. The final clause above requires that certain 
common values always be boxed into indistinguishable objects. The implementation may  
cache these, lazily or eagerly. For other values, this formulation disallows any 
assumptions about the identity of the boxed values on the programmer's part. This would 
allow (but not require) sharing of some or all of these references.

This ensures that in most common cases, the behavior will be the desired one, without     
imposing an undue performance penalty, especially on small devices. 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.`

Вот исходный код Oracle Doc< /а>

person MaheshVarma    schedule 31.05.2013

Ответ на ваши сомнения

  1. автоупаковка и автораспаковка в Java, которая преобразует примитивные объекты в объекты класса-оболочки и наоборот соответственно.
  2. автоупаковка означает, что внутри компилятор использует метод valueOf() примитивных классов, а автораспаковка означает, что внутри компилятор использует метод xxxValue().
  3. Предположим, что для частного недействительного вычисления (Long a, Long b, Long c) { long result = a-(b+c);

это делает это преобразование a.longValue()-(b.longValue()+c.longValue()) Это означает, что даже до того, как ваш оператор выполняет сложение, компилятор предоставляет примитивы типа long в качестве входных данных для вашего операнды Помните, что это идет рука об руку, поскольку JAVA является статически и строго типизированным языком.

Следовательно, вы получаете вывод длинного типа

Надеюсь, я развеял ваши сомнения

person NAGHMAAN MOHASEEN    schedule 16.05.2019
comment
Привет, во-первых, ваш ответ на самом деле не является ответом, так как механизм, который вы здесь объясняете (autoboxing и unboxing), преобразующий объекты Long в примитивы long, также может преобразовать результат в объект Long, если бы он был Long result = a-(b+c);. Во-вторых и последнее, ваш пост плохо отформатирован, структура 1/2/3 вообще не имеет смысла. - person SherloxTV; 16.05.2019
comment
Конечно, сэр, если вы утверждаете, что это неправильно, пожалуйста, просветите меня правильным анализом. и больше никогда, если там будет длинный результат, то снова будет шаг автобокса - person NAGHMAAN MOHASEEN; 16.05.2019
comment
Я не буду, потому что я был здесь не для этого. Я просто просматриваю поздние ответы. Я просто говорю, что ваш ответ бесполезен, так как он просто говорит то же самое, что и ответ Майкла Боргвардта, который был опубликован в тот же день, что и вопрос. Но его лучше форматировать, объяснять/разрабатывать. Если вы хотите помочь другим, отвечайте на вопросы, которые необходимо, и заботьтесь о полезности и форматировании этого. - person SherloxTV; 16.05.2019
comment
Спасибо за ответ. Обязательно воспользуюсь вашим советом в будущем. - person NAGHMAAN MOHASEEN; 26.05.2019