通过源码了解Java的自动装箱拆箱
什么叫装箱 & 拆箱?
将int基本类型转换为Integer包装类型的过程叫做装箱,反之叫拆箱。
首先看一段代码
public static void main(String[] args) {
Integer a = 127, b = 127;
Integer c = 128, d= 128;
System.out.println(a == b); // true
System.out.println(c == d); // false
}
不知道还有没有人不知道这段代码出现true和false的原因。由此我们引出了Java装箱的这个操作。我们带着疑问去进行分析。
装箱(valueOf())
public static Integer valueOf(int i) {
// -128 - 127
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
我们可以发现,在最开始有一个判断,如果这个值的范围在[-128,127]之间,那么就从这个缓存(Integer数组)中取,如果不在这个范围那么直接new一个。
为什么要有[-128,127]的缓存?
我说说的理解,因为在我们的业务中,可能存在各种状态和标识等Integer类型的字段,这些值一般都是0,1,2,3之类的,而且出现的比较频繁,如果没有缓存,那么就需要频繁的new对象,然后再释放,就非常消耗内存空间,所以对于这个缓存就出现了,可以极大的帮助我们优化一些空间上的浪费。
为什么是[-128,127]?
这个我看了一下,具体为什么这里就不详说了,主要还是依赖计算机基础知识,在你了解了什么是原码、反码、补码。就很容易知道为什么是这个范围区间了。
这个值也是可以通过启动参数进行更改的。
-XX:AutoBoxCacheMax=(size)
自动装箱带来的性能问题
那么看到现在你应该明白上面代码出现不同结果的原因了,那么你有没有想过,比如我们业务中一个for循环中,出现了统计数据类似这样的操作,如果存在自动装箱,那么会出现什么问题?我们看下面一段代码。
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
Integer count = 0;
// int count = 0;
for (int i = 0; i < 5000000; i++) {
count += i;
}
System.out.println("计算时长:" + (System.currentTimeMillis() - startTime) + " ms");
}
// 执行结果:
// Integer 计算时长:51 ms
// int 计算时长:6 ms
那么通过执行结果可以明显的发现自动装箱频繁的new对象、分配内存,造成时间和空间上的性能损耗。
小总结
通过上面的源码阅读和测试分析,我们可以得出结论,我们平时在进行计算统计,或者方法入参的时候,应该尽量的避免这种类型转换的问题。来提升我们整个代码的执行效率。
拆箱(intValue)
拆箱总体没有什么复杂的逻辑,直接返回这个数值的基本类型。
本文来自博客园,作者:一个程序员的成长,转载请注明原文链接:https://www.cnblogs.com/bingfengdada/p/16169715.html