自动装箱、拆箱了解多少?

写在前面

Java 为我们提供了 8 种基本数据类型,为什么还需要提供各自的包装类型呢?您可能会觉得这个问题问的很奇怪,但是我觉得还是值的思考的。

因为 Java 是一门面向对象的语言,基本数据类型并不具备对象的性质。而包装类型则是在基本类型的基础上,添加了属性和方法,从而成为了对象。试想,一个 int 类型怎么添加到 List 集合中?

如何理解Java中的自动拆箱和自动装箱?

自动拆箱?自动装箱?什么鬼,听都没听过啊,这...这..知识盲区...

回到家后赶紧查资料,我透,这不就是问基本类型跟封装类型吗,面试官整啥名词呢...

别问结果,问就是没过。

自动装箱、拆箱

定义: 基本数据类型和包装类之间可以自动地相互转换

理解: 装箱就是自动将基本数据类型转换为封装类型,拆箱就是自动将封装类型转换为基本数据类型。

我们来看个例子:

Integer number = 10; // 自动装箱
int count = number; // 自动拆箱

我们知道,Java 中提供了四大类基本数据类型,分别是:整数、浮点数、字符型和布尔型,其中:

  • 整数包含:byte、int、short、long
  • 浮点数包含:float、double
  • 字符类型:char
  • 布尔类型:boolean

基本数据类型相信大家一定很熟悉了吧,来来来,说说他们的取值范围~

数据类型 取值范围
byte -128 ~ 127
short -32786 ~ 32767
int -4294967296 ~ 4294967295
long -264 ~ 264 -1
float 3.4e-038 ~ 3.4e+038
dubbo 1.7e-308 ~ 1.7e+308
char \u0000 ~ \uffff
boolean true 、false

日常开发中,靠这些基本数据类型几乎能够满足我们的需求,但是基本类型终究不是对象,往重了说不满足面向对象的开发思想,往轻了说就是使用不方便。怎么讲?例如做一些数据类型转换,获取 int 数据类型的取值范围等等。

我们知道,类的优点在于它可以定义成员变量、成员方法,提供丰富便利的功能,因此 Java 在 JDK1.0 的时候就设计了基本数据类型的包装类,而在 JDK1.5 中引入了新特性:自动装箱和拆箱。

我们来看一下基本类型跟封装类型之间的对应关系:

数据类型 封装类
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

何时会发生拆箱、装箱?

自动装箱和拆箱在 Java 中很常见,比如我们有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么 Java 会自动将这个原始类型值转换成与之对应的对象。最经典的一个场景就是当我们向 ArrayList 这样的容器中增加原始类型数据时或者是创建一个参数化的类,比如下面的 ThreadLocal。

ArrayList<Integer> intList = new ArrayList<Integer>();
intList.add(1); // 装箱
intList.add(2); // 装箱

ThreadLocal<Integer> intLocal = new ThreadLocal<Integer>();
intLocal.set(4); // 装箱

int number = intList.get(0); // 拆箱
int local = intLocal.get(); // 拆箱

上面的示例我们介绍了自动装箱和拆箱以及它们何时发生,我们知道了自动装箱主要发生在两种情况,一种是赋值时,另一种是在方法调用的时候。

赋值时

这是最常见的一种情况,在 Java 1.5 以前我们需要手动地进行转换才行,而现在所有的转换都是由编译器来完成。

// before autoboxing
Integer iObject = Integer.valueOf(3);
int iPrimitive = iObject.intValue()

//after java5
Integer iObject = 3; // autobxing - primitive to wrapper conversion
int iPrimitive = iObject; // unboxing - object to primitive conversion

方法调用时

这是另一个常用的情况,当我们在方法调用时,我们可以传入原始数据值或者对象,同样编译器会帮我们进行转换。

public static Integer show(Integer iParam){
   System.out.println("autoboxing example - method invocation i: " + iParam);
   return iParam;
}

// autoboxing and unboxing in method invocation
show(3); // autoboxing
int result = show(3); // unboxing because return type of method is Integer

show() 方法接受 Integer 对象作为参数,当调用 show(3) 时,会将 int 值转换成对应的 Integer 对象,这就是所谓的自动装箱,show() 方法返回 Integer 对象,而 int result = show(3); 中 result 为 int 类型,所以这时候发生自动拆箱操作,将 show() 方法返回的 Integer 对象转换成 int 值。

自动装拆箱的弊端

自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的情况,如下面的例子就会创建多余的对象,影响程序的性能。

Integer sum = 0;
for(int i=1000; i<5000; i++){
   sum += i;
}

上面的代码 sum += i 可以看成 sum = sum + i,但是 + 这个操作符不适用于 Integer 对象,首先 sum 进行自动拆箱操作,然后进行数值相加操作,最后发生自动装箱操作转换成 Integer 对象。其内部变化如下:

int result = sum.intValue() + i;
Integer sum = new Integer(result);

由于我们这里声明的 sum 为 Integer 类型,在上面的循环中会创建将近 4000 个无用的 Integer 对象,在这样庞大的循环中,会降低程序的性能并且加重了垃圾回收的工作量。因此在我们编程时,需要注意到这一点,正确地声明变量类型,避免因为自动装箱引起的性能问题。

总结

因为自动装箱会隐式地创建对象,像前面提到的那样,如果在一个循环体中,会创建无用的中间对象,这样会增加 GC 压力,降低程序的性能。所以在写循环时一定要注意,避免引入不必要的自动装箱操作。

总的来说,自动装箱和拆箱着实为开发者带来了很大的方便,但是在使用时也是需要格外留意,避免引起出现文章提到的问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容

  • 每章一点正能量:每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。 前言 最近在回顾复习Java基础中的一些...
    Coder编程阅读 936评论 0 1
  • 先说Integer和int的区别 Integer是int的包装类,int是基本数据类型; Integer变量必须实...
    xlq阅读 755评论 0 0
  • 小伟刚毕业时面的第一家公司就被面试官给问住了,记忆尤深啊... 如何理解Java中的自动拆箱和自动装箱? 自动拆箱...
    niceyoo_阅读 7,073评论 0 2
  • 什么的拆装箱 我第一次听到这个概念是一脸懵逼的,而其实最常使用的地方就是我们熟悉的包装类的使用中.比如将int的变...
    _ALID阅读 570评论 0 0
  • 参考文章:深入剖析Java中的装箱和拆箱 一、什么是装箱/拆箱 在讲之前,得先提一下为什么两个概念:基本数据类型及...
    12313凯皇阅读 1,553评论 0 1