摘要:文章主要介绍通过改进就已存在的骨灰级特性大幅度提高应用性能。在继续解释造成差异的细节之前,让我们仔细回味一下中的这两个概念自动装箱与拆箱。
【编者按】本文作者为 Ali Kemal TASCI,最早于2016年4月9日发布于DZONE社区。文章主要介绍通过改进 Java 1.5 就已存在的骨灰级特性大幅度提高应用性能。
本文系 OneAPM 工程师编译呈现,以下为正文。
如果我告诉你:“只要修改一个字符,下面这段代码的运行速度就能提高5倍。”,你觉得可能么?
long t = System.currentTimeMillis(); Long sum = 0L;for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println("total:" + sum); System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms");
输出结果:
总数:2305843005992468481
处理时间:6756 ms
仔细琢磨一下,你可能会想到下面这种执行速度更快的实现方法:
long t = System.currentTimeMillis();//Long sum = 0L;long sum = 0L;for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println("total:" + sum); System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms") ;
输出结果:
总数:2305843005992468481
处理时间:1248 ms
其实,自动装箱(Autoboxing)的草率使用是造成速度差异的根本原因,而这一特性从 Java 1.5 开始就已出现了。
在继续解释造成差异的细节之前,让我们仔细回味一下 Java 中的这两个概念:自动装箱(Autoboxing)与 拆箱(Unboxing)。
Java 中的变量分为两种:原始型与引用型。一共存在8个原始型变量以及与各个原始变量对应的8个引用变量(包装类)。
Primitive Types(原始型) | Reference Types(Wrapper Class)(引用型,(包装类)) |
---|---|
boolean | Boolean |
byte | Byte |
char | Character |
float | Float |
int | Integer |
long | Long |
short | Short |
double | Double |
下面的代码会介绍”Autoboxing“与”Unboxing“的用例。在这段代码中,一个类型为”long”的值被添加到类型为”Long“的List集合中。在 Java 1.4 中,为了实现此操作,我们必须将原始变量赋值到合适的引用类中(也即装箱,boxing)。从 Java 1.5 开始,编译器会帮我们完成这一操作。所以,我们不再需要写那么多代码。
ListlongList = new ArrayList<>(); long i = 4; longList.add( i ); //autoboxing long j = longList.get( 0 ); //unboxing
从 Java 1.5 开始,编译器会自动将上面的代码段转化成如下代码:
ListlongList = new ArrayList<>(); long i = 4; longList.add(Long.valueOf( i ) ); long j = longList.get( 0 ).longValue();
因此,我们也可以说,前文出现的第一段代码段会自动转化为如下代码。所以,导致处理时间较长的原因也就水落石出了:不必要地创建了2147483647个”Long“类型实例。
long t = System.currentTimeMillis(); Long sum = 0L;for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += new Long(i); } System.out.println("total:" + sum); System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms") ;
由此可知,想要编写速度更快的 Java 代码,我们也需要考虑”Autoboxing”与”Unboxing”这样的基础概念。
相关资源集锦Autoboxing and Unboxing
Autoboxing
Efective Java 2nd Edition, J. Bloch
OneAPM 为您提供端到端的 Java 应用性能解决方案,我们支持所有常见的 Java 框架及应用服务器,助您快速发现系统瓶颈,定位异常根本原因。分钟级部署,即刻体验,Java 监控从来没有如此简单。想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客
原文地址:https://dzone.com/articles/java-performance-notes-autoboxing-unboxing
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65808.html
摘要:本章部分内容从源码中解读一些自动装箱与拆箱的原理,以及会出现的一些陷阱已经性能等。例题分析我们通过几个经典的问题,来看看大家到底理解了装箱与拆箱的知识点没。 showImg(https://img-blog.csdnimg.cn/20190426221838971.gif);showImg(https://img-blog.csdnimg.cn/20190426221918208.pn...
摘要:但是,三目运算符也是有一定的语言规范的。一三目运算符对于条件表达式,先计算条件,然后进行判断。那么,这段代码为什么会自动拆箱呢这其实是三目运算符的语法规范。所以,结果就是由于使用了三目运算符,并且第二第三位操作数分别是基本类型和对象。 三目运算符是我们经常在代码中使用的,a= (b==null?0:1);这样一行代码可以代替一个if-else,可以使代码变得清爽易读。 但是,三目运算符...
自动装箱和拆箱 自动装箱是Java编译器在基元类型和相应的对象包装类之间进行的自动转换,例如,将int转换为Integer,将double转换为Double,依此类推,如果转换是另一种方式,则称为拆箱。 以下是自动装箱的最简单示例: Character ch = a; 本节中的其余示例使用泛型,如果您还不熟悉泛型的语法,请参阅泛型课程。 考虑以下代码: List li = new ArrayLis...
摘要:整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。这种缓存策略仅在自动装箱的时候有用,使用构造器创建的对象不能被缓存。行的结果为而行则为。所以行的结果为而行为。中其他类似的缓存的缓存上限可以通过虚拟机参数修改,的缓存则没法修改。 Java5为Integer的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用。上面的规则默...
阅读 1816·2021-09-29 09:35
阅读 2672·2021-09-22 15:25
阅读 1940·2021-08-23 09:43
阅读 2012·2019-08-30 15:54
阅读 3291·2019-08-30 15:53
阅读 2356·2019-08-30 13:50
阅读 2360·2019-08-30 11:24
阅读 2224·2019-08-29 15:37