自动装箱的性能影响
通常编译器会生成代码来执行装箱和拆箱。但是,如果不需要装箱值,编译器会做什么呢? (Oracle 标准)编译器是否足够智能来优化它?
看一下这个方法:
public static void requireInRange(int index, Object[] array) {
if(index < 0 || index >= array.length)
throw new IndexOutOfBoundsException();
}
唯一相关的信息是 array.length,因此对数组的每个值进行装箱是没有用的。就像这段代码一样:
int[] anArray = {3, 4, 2};
requireInRange(3, anArray);
编译器实际上会插入代码来装箱数组的每个值吗?
Usually the compiler generates code to perform boxing and unboxing. But what does the compiler, if the boxed values are not needed? Is the (Oracle standard) compiler smart enough to optimize it away?
Take a look at this method:
public static void requireInRange(int index, Object[] array) {
if(index < 0 || index >= array.length)
throw new IndexOutOfBoundsException();
}
The only relevant information is the array.length
, so it would be useless to box each value of an array for example. Like in this code:
int[] anArray = {3, 4, 2};
requireInRange(3, anArray);
Will the compiler actually insert code for boxing each value of the array?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的代码中没有自动装箱。事实上,假设:
虽然
int
可以自动装箱为Integer
,但int[]
却不能由 Java 自动装箱为Integer[]
。您可以编写库函数来执行此操作,但该语言不会促进此转换。这实际上是关于例如
Arrays.asList(anIntArray)
被“损坏”的许多混乱的根源,因为返回的不是List
,而是实际上是一个单元素List
。但性能呢?
引用自 Java 语言指南/Autoboxing:
简而言之,每当自动装箱发生时,性能肯定会受到一点影响。某些东西有助于缓解这种情况,例如这些类型中内置的缓存机制。这就是为什么您会得到以下结果:
这里发生的情况是,当
0
自动装箱时,没有newInteger
实例实际上已创建:出于自动装箱目的缓存特定范围内的值,以提高性能。在大多数实现中,10000
可能超出此范围,但某些 JVM 实现确实允许您在必要时指定缓存范围。但我只想得到数组的长度!
有很多方法可以帮助您的
requireInRange
处理任何类型的数组。不幸的是,使用 Java 的原语数组通常意味着大量的重复。这意味着为int[]
、boolean[]
、byte[]
、Object[]
等提供重载分别地。更简洁的选择是使用反射,但这有其优点和缺点。一般来说,反射不应该是大多数场景的首选解决方案。
话虽如此,
java.lang。 Reflect.Array
确实有一个int getLength(Object array)
static
方法,可以返回ANY<的长度/em> 数组。它不是类型安全的(就像大多数反射机制一样);传递非数组可以编译,但在运行时抛出IllegalArgumentException
。相关问题
java.util.Arrays< /代码>
)
There is no autoboxing in your code. In fact, given:
While an
int
can be autoboxed to anInteger
, anint[]
does NOT get autoboxed toInteger[]
by Java. You can write library functions to do this, but the language will not facilitate this conversion.This is in fact the source of many confusion regarding e.g.
Arrays.asList(anIntArray)
being "broken", because instead of returning aList<Integer>
, what is returned is in fact a one-elementList<int[]>
.But what about performance???
A quote from Java Language Guide/Autoboxing:
In short, whenever autoboxing happens, performance definitely takes a little bit of a hit. Certain things help to alleviate this, e.g. the caching mechanism built into these types. This is why you get the following:
What happened here is that when
0
is automatically boxed, no newInteger
instance is actually created: values in certain range is cached for autoboxing purposes, to help performance.10000
in most implementation probably falls out of this range, but some JVM implementations do allow you to specify the cache range if necessary.But I just want to get the length of the array!!!
There are many ways to facilitate your
requireInRange
to work with any type of arrays. Unfortunately working with Java's array of primitives often times mean lots of repetition. This mean providing overloads forint[]
,boolean[]
,byte[]
,Object[]
, etc separately.A more concise option is to use reflection, but this has its pluses and minuses. Generally speaking, reflection should not be the preferred solution for most scenarios.
Having said that,
java.lang.reflect.Array
does have aint getLength(Object array)
static
method that can return the length of ANY array. It's not typesafe (like most reflection mechanism are); passing a non-array compiles, but throwsIllegalArgumentException
at run-time.Related questions
java.util.Arrays
)编译器将拒绝该代码,因为
int[]
无法传递到采用Object[]
参数的方法中。自动装箱仅适用于单个原始值,而不适用于整个数组。
The compiler will reject the code because an
int[]
cannot be passed into a method that takes anObject[]
parameter.Autoboxing happens only for individual primitive values, never for entire arrays.
如果有疑问,您可以假设编译器没有优化代码。一般来说,它会对代码进行直译。
此外,如果有疑问,您可以假设 JVM 在运行时优化代码方面做得非常好。我不认为它有任何区别,除非您有充分的理由(例如分析器)怀疑这是一个问题。
If in doubt, you can assume the compiler does not optimize the code. Generally, it does a literal translation of the code.
Additionally, if in doubt, you can assume the JVM does a very good job of optimizing the code at runtime. I wouldn't assume it makes any difference unless you have a good reason (such as profiler) to suspect it is a problem.