简体   繁体   English

在Java中长时间取消装箱

[英]Unboxing Long in java

In some code I see this: 在一些代码中,我看到了这一点:

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

It seems a bit strange that the result is stored in a primitive long instead of a Long object corresponding to its operands. 结果存储在原始long中而不是对应于其操作数的Long对象中,这似乎有点奇怪。

Are there any reason that a result should be stored as a primitive? 是否有任何理由将结果存储为原语?

It seems a bit strange that the result is stored in a primitive long instead of a Long object corresponding to its operands. 结果存储在原始long中而不是对应于其操作数的Long对象中,这似乎有点奇怪。

No, what is "strange" is that you can use the + and - operators on Long objects. 不,“奇怪”是您可以在Long对象上使用+-运算符。 Before Java 5, this would have been a syntax error. 在Java 5之前,这可能是语法错误。 Then autoboxing/unboxing was introduced. 然后介绍了自动装箱/拆箱。 What you're seeing in this code is autounboxing : the operators require primtives, so the compiler automatically inserts a call to longValue() on the objects. 您在这段代码中看到的是自动拆箱 :运算符需要原语,因此编译器会自动在对象上插入对longValue()的调用。 The arithmetic is then performed on primitive long values, and the result is also a long that can be stored without further conversion on the variable. 然后对原始long值执行算术运算,结果也是long ,可以存储该long ,而无需在变量上进行进一步转换。

As for why the code does this, the real question is why someone would use the Long type instead of long . 至于为什么代码要这样做,真正的问题是为什么有人会使用Long类型而不是long类型。 Possible reasons: 可能的原因:

  • The values come from some library/API that delivers Long values. 这些值来自提供Long值的某些库/ API。
  • The values are stored in collections ( List , Map ), which cannot hold primitives. 值存储在不能保存基元的集合( ListMap )中。
  • Sloppiness or cargo cult programming . 松懈或货物崇拜程序设计
  • The ability to have null values is required, eg to signal unavailable or uninitialized data. 需要具有null值的功能,例如,用信号通知不可用或未初始化的数据。

Note that the ability of Long to hold null values means that the calculation (or more specifically, the longValue() calls inserted by the compiler) can fail with a NullPointerException - a possibility the code should deal with somehow. 请注意, Long保留null值的能力意味着计算(或更具体地说,由编译器插入的longValue()调用)可能会因NullPointerException失败-代码应以某种方式处理这种可能性。

原因很明显:result被声明为原始。

The arithmetic operators + and - are not defined for boxed types (eg Long) but for primitive types (eg long). 算术运算符+和-不是为装箱类型(例如Long)定义的,而是为基本类型(例如long)定义的。

The result is also a long. 结果也很长。 See Autoboxing and Unboxing tutorial 请参阅自动装箱和拆箱教程

Autoboxing this into a Long would result in a small performance cost. 将其自动装箱成Long可能会降低性能成本。 It is also unnecessary because 这也是不必要的,因为

  1. We know it will be non-null (if a, b or c were null, a NullPointerException would occur). 我们知道它将为非null(如果a,b或c为null,则将发生NullPointerException)。
  2. It would be autoboxed implicitly if we use it later where a Long is required. 如果稍后在需要Long的地方使用它,它将被隐式自动装箱。

Based on your needs.I mean the decelaration. 根据您的需要。

Autoboxing and unboxing can happen anywhere where an object is expected and primitive type is available Autoboxing unboxingunboxing可以在需要对象和原始类型可用的任何地方进行

Usually you should prefer using primitives, especially if you are certain they cannot be null. 通常,您应该更喜欢使用基元,尤其是当您确定基元不能为null时。 If you insist on using the boxed types always think extra hard about what happens when it is null. 如果您坚持使用盒装类型,请务必加倍思考当它为null时会发生什么。 Java will do the boxing and unboxing automatically for you, but staring at an int and wondering why you got a NullPointerException can be fun. Java将自动为您进行装箱和拆箱,但是盯着一个int并想知道为什么会出现NullPointerException可能很有趣。

从Java 1.5开始,自动装箱和拆箱会在需要时隐式发生。

The following line: 下一行:

long result = a-(b+c);

...asks Java to take the result of the expression using 3 Long s, and then store it in a primitive long. ...要求Java使用3 Long来获取表达式的结果,然后将其存储在原始long中。 Before Java 5, it would complain about the types not matching - but these days it just assumes you mean what you say and automatically does the conversion from object to primitive type for you. 在Java 5之前,它会抱怨类型不匹配-但是如今,它仅假设您的意思,并自动为您完成从对象到原始类型的转换。

In this example however, unless there's some other good reason not presented here, there's absolutely no point having the parameters as the boxed, object type in the first place. 但是,在此示例中,除非这里没有给出其他一些充分的理由,否则绝对没有理由首先将参数作为盒装对象类型。

As per the javadoc 根据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.`

Here is the Oracle Doc source 这是Oracle Doc源

The answer for your doubt is 您的疑问的答案是

  1. autoboxing and autounboxing in Java which converts from primitive to wrapper class objects and vice versa respectively. Java中的自动装箱和自动拆箱,分别从原始类转换为包装类对象,反之亦然。
  2. autoboxing means internally compiler uses valueOf() method of primitive classes ans autounboxing means internally compiler uses xxxValue() method. 自动装箱意味着内部编译器使用原始类的valueOf()方法;自动拆箱意味着内部编译器使用xxxValue()方法。
  3. Suppose for private void compute(Long a, Long b, Long c) { long result = a-(b+c); 假设有私有无效计算(Long a,Long b,Long c){long result = a-(b + c);

its makes this conversion a.longValue()-(b.longValue()+c.longValue()) Which means even before your statement performs addition the compiler provides the primitives of long type as input to your operands Remember that this goes in hand as JAVA is statically and strongly typed language. 它使此转换为a.longValue()-(b.longValue()+ c.longValue()),这意味着即使在您的语句执行加法运算之前,编译器也会将long类型的原语提供为操作数的输入。因为JAVA是静态和强类型语言。

Hence you get long type output 因此,您得到长型输出

I hope i cleared your doubt 我希望我消除了你的疑虑

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM