Java 性能要点:自动装箱/ 拆箱 (Autoboxing / Unboxing)

【编者按】本文作者为 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 开始,编译器会帮我们完成这一操作。所以,我们不再需要写那么多代码。

List<Long> longList = new ArrayList<>();
long i = 4;
longList.add( i ); //autoboxing      long j = longList.get( 0 ); //unboxing

从 Java 1.5 开始,编译器会自动将上面的代码段转化成如下代码:

List<Long> longList = 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 官方博客

原文地址:https://dzone.com/articles/java-performance-notes-autoboxing-unboxing

时间: 2024-08-30 12:04:38

Java 性能要点:自动装箱/ 拆箱 (Autoboxing / Unboxing)的相关文章

java自动装箱拆箱深入剖析_java

这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的(在这种情况下包装成为装箱,解包装称为拆箱): 其实按照我自己的理解自动装箱就可以简单的理解为将基本数据类型封装为对象类型,来符合java的面向对象:例如用int来举例: 复制代码 代码如下: //声明一个Integer对象 Integer num = 10; //以上的声明就是用到了自动的装箱:解析为 Integer nu

java 自动装箱拆箱实现方法

java 自动装箱拆箱实现方法 什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自j2se 5.0开始提供的功能.  一般我们要创建一个类的对象的时候,我们会这样: class a = new class(parameter); 当我们创建一个integer对象时,却可以这样: integer i = 100; (注意:不是 int i = 100; ) 实际上,上面那句代码相当于:integer i = new integer(100); 此即基本

Java基础笔记 – 增强的for循环For each循环 自动装箱拆箱 可变参数

1.For each循环:1.1.语法:1.2.For each循环的使用:1.3.嵌套For each循环:1.4.三种循环遍历集合的列举:1.5.增强的for循环的缺点:2.自动装箱/拆箱(Autoboxing/unboxing):2.1.自动装箱:2.2.自动拆箱:2.3.Integer类相关的源代码:2.3.1.valueOf方法:3.可变参数:3.1.包含可变参数的函数:3.2.接收参数:3.3.说明: 1.For each循环: JDK5.0中提供的新特性For each循环的加入简

Java学习之自动装箱和自动拆箱源码分析

自动装箱(boxing)和自动拆箱(unboxing) 首先了解下Java的四类八种基本数据类型 基本类型 占用空间(Byte) 表示范围 包装器类型 boolean 1/8 true|false Boolean char 2 -128~127 Character byte 1 -128~127 Byte short 2 -2ˆ15~2ˆ15-1 Short int 4 -2ˆ31~2ˆ31-1 Integer long 8 -2ˆ63~2ˆ63-1 Long float 4 -3.403E38

装箱拆箱中内存分布的流程

问题描述 装箱拆箱中内存分布的流程 装箱问题,我在msdn上看到的说明又变糊涂了; object o=1; 我们知道这里发生了装箱,在堆上开辟了内存空间并且返回了一个引用给o,这个o现在是谁?(我原来理解就是这个新开辟的内存就是o,那这个引用返回给谁?) 我在msdn上看到说是栈上面的"The result of this statement is creating an object reference o, on the stack, that references a value of t

list-link中使用List&amp;amp;lt;object&amp;amp;gt;还需要装箱拆箱么?

问题描述 link中使用List<object>还需要装箱拆箱么? link中使用List还需要装箱拆箱么? 解决方案 首先搞清楚,装箱拆箱在什么情况下发生,当你将堆栈上的变量放入维持object引用的集合的时候,必然要装箱.试想,如果List不装箱,而直接存int,那么它存另一种类型,比如string 存入的是引用(地址),岂不是乱套了,它怎么知道这个是int的值还是string的引用.所以必须都装箱成对象. 所以结论就是,需要.

Java JDK之自动装箱和拆箱

基本数据(Primitive)类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能.虽然为您打包基本数据类型提供了方便,但提供方便的同时表示隐藏了细节,建议在能够区分基本数据类型与对象的差别时再使用. autoboxing和unboxing 在Java中,所有要处理的东西几乎都是对象 (Object),例如之前所使用的Scanner是对象,字符串(String)也是对象,之后还会看到更多的对象.然而基本(Primitive)数据类型不是对象,也就是您

C#中的“装箱”(boxing)与“拆箱”(unboxing)

装箱和拆箱:任何值类型.引用类型可以和object(对象)类型之间进行转换.装箱转换是指将一个值类型隐式或显式地转换成一个object类型,或者把这个值类型转换成一个被该值类型应用的接口类型(interface-type).把一个值类型的值装箱,就是创建一个object实例并将这个值复制给这个object,装箱后的object对象中的数据位于堆中,堆中的地址在栈中.被装箱的类型的值是作为一个拷贝赋给对象的.如:int i = 10;object obj = i; //隐式装箱object obj

C#装箱拆箱操作演示代码

  C#装箱和拆箱操作的演示代码,不知道什么是装箱和拆箱的这里就不介绍了,是栈和堆的使用方面的东西,C#专业达人应该都知道,所以这里就不哆嗦了,代码也是面向C#新手的,挺简单: