目的:

自动装箱和拆箱从Java 1.5开始引入,目的是将原始类型值转自动地转换成对应的对象,以使用对象的API和引用类型操作。自动装箱与拆箱的机制可以让我们在Java的变量赋值或者是方法调用等情况下使用原始类型或者对象类型更加简单直接。

定义:

自动装箱就是Java自动将原始类型值转换成对应的对象,比如将int的变量转换成Integer对象,这个过程叫做装箱,反之将Integer对象转换成int类型值,这个过程叫做拆箱。因为这里的装箱和拆箱是自动进行的非人为转换,所以就称作为自动装箱和拆箱。原始类型byte,short,char,int,long,float,double和boolean对应的封装类为Byte,Short,Character,Integer,Long,Float,Double,Boolean。

实现:

自动装箱时编译器调用valueOf将原始类型值转换成对象,同时自动拆箱时,编译器通过调用类似intValue(),doubleValue()这类的方法将对象转换成原始类型值。

发生时间:

有一个方法,接受一个对象类型的参数,如果我们传递一个原始类型值,那么Java会自动讲这个原始类型值转换成与之对应的对象。

List<Integer> list = new ArrayList<Integer>();

// 自动装箱

list.add(1);

list.add(2);

// 拆箱

int i = list.get(0);

int ii = list.get(1);

自动装箱的弊端:

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

Integer sum = 0;

for(int i=1000; i<5000; i++){

sum+=i;

}

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

int temp = sum.intValue() + i;

Integer sum = new Integer(temp);

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

注意事项:

自动装箱和拆箱可以让代码简洁,但是,我们在使用的时候应该注意下,否则会发生一些问题。

1.比较

”==“可以用于原始值进行比较,也可以用于对象进行比较,当用于对象与对象之间比较时,比较的不是对象代表的值,而是检查两个对象是否是同一对象,即检查引用地址是否相同。这个比较过程中没有自动装箱发生。进行对象值比较不应该使用”==“,而应该使用对象对应的equals方法。

// 1

int i1=1;

int i2=1;

System.out.println(i2==i1);// true

// 2

Integer I1=1;

System.out.println(I1==i1);// true

Integer I2=1;

System.out.println(I1==I2);// true

// 3

Integer I3 = 128;// 触发自动封装

Integer I4 = 128;

System.out.println(I3==I4);// false

// 4

Integer I5= new Integer(1);// 不触发自动封装

Integer I6= new Integer(1);

System.out.println(I5==I6); // false

值得注意的是第2个小例子的第二个比较,这是一种极端情况。I1和I2的初始化都发生了自动装箱操作。但是处于节省内存的考虑,JVM会缓存-128到127的Integer对象。因为I1和I2实际上是同一个对象。所以使用”==“比较返回true,而第三个小例子使用‘==’返回false。

注:自动封装的函数

public static Integer valueOf(int i) {

return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];

}

private static final Integer[] SMALL_VALUES = new Integer[256];

2.容易混乱的对象和原始数据值

另一个需要避免的问题就是混乱使用对象和原始数据值,一个具体的例子就是当我们在一个原始数据值与一个对象进行比较或赋值时,如果这个对象没有进行初始化或者为Null,在自动拆箱过程中obj.xxxValue,会抛出NullPointerException,如下面的代码

private static Integer count;

if(count>=0){

System.out.println(11111111111L);

}

3.缓存的对象

在Java中,会对-128到127的Integer对象进行缓存,当创建新的Integer对象时,如果符合这个这个范围,并且已有存在的相同值的对象,则返回这个对象,否则创建新的Integer对象。

4.生成无用对象

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

Java数据类型(2)------自动封装拆箱的更多相关文章

  1. Java中的自动装箱拆箱

    Java中的自动装箱拆箱 一.自动装箱与自动拆箱 自动装箱就是将基本数据类型转换为包装类类型,自动拆箱就是将包装类类型转换为基本数据类型. 1 // 自动装箱 2 Integer total = 90 ...

  2. Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法?

    参考:http://blog.csdn.net/mazhimazh/article/details/16799925 1. Java八种基本数据类型的大小,以及封装类,自动装箱/拆箱的用法? 原始类型 ...

  3. JAVA自动装箱拆箱与常量池

    java 自动装箱与拆箱 这个是jdk1.5以后才引入的新的内容,作为秉承发表是最好的记忆,毅然决定还是用一篇博客来代替我的记忆: java语言规范中说道:在许多情况下包装与解包装是由编译器自行完成的 ...

  4. Java 的自动装箱拆箱

    Java 是面向对象的语言,其基本数据类型也就有了相对应的类,称为包装类.以下是基本数据类型对应的包装类: 基本数据类型 包装类 byte(1字节) Byte short(2字节) Short int ...

  5. Java SE之装箱与拆箱【基本数据类型的包装类/==与equals方法】

     对象包装器.自动装箱与拆箱   2016/11/30  晚   特点       1.所有的基本类型都有一个包装器类与之对应.[Integer,Boolean,Long,Character,Shor ...

  6. java基础1.5版后新特性 自动装箱拆箱 Date SimpleDateFormat Calendar.getInstance()获得一个日历对象 抽象不要生成对象 get set add System.arrayCopy()用于集合等的扩容

    8种基本数据类型的8种包装类 byte Byte short Short int Integer long Long float Float double Double char Character ...

  7. Java的自动装箱/拆箱

    概述 自JDK1.5开始, 引入了自动装箱/拆箱这一语法糖, 它使程序员的代码变得更加简洁, 不再需要进行显式转换.基本类型与包装类型在某些操作符的作用下, 包装类型调用valueOf()方法将原始类 ...

  8. JAVA的自动装箱拆箱

    转自:http://www.cnblogs.com/danne823/archive/2011/04/22/2025332.html 蛋呢  的空间 ??什么是自动装箱拆箱 基本数据类型的自动装箱(a ...

  9. java自动装箱拆箱总结

    对于java1.5引入的自动装箱拆箱,之前只是知道一点点,最近在看一篇博客时发现自己对自动装箱拆箱这个特性了解的太少了,所以今天研究了下这个特性.以下是结合测试代码进行的总结. 测试代码: int a ...

随机推荐

  1. 洛谷1439:最长公共子序列(nlogn做法)

    洛谷1439:最长公共子序列(nlogn做法) 题目描述: 给定两个序列求最长公共子序列. 这两个序列一定是\(1\)~\(n\)的全排列. 数据范围: \(1\leq n\leq 10^5\) 思路 ...

  2. JAVA并归排序(数组+链表)

    并归排序与快速排序相似,靠分治思想突破了排序算法 O(n2) 的瓶颈. 我们看回顾一下几大排序算法的时间.空间复杂度: 排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 是否稳定 冒泡排序 O(n ...

  3. [LeetCode] 327. Count of Range Sum 区间和计数

    Given an integer array nums, return the number of range sums that lie in [lower, upper] inclusive.Ra ...

  4. CentOS6.9安装MySQL5.6

    1 检查系统是否自带MySQL 检查系统是否自带MySQL yum list installed | grep mysql 下面结果说明系统自带MySQL 卸载系统自带MySQL yum -y rem ...

  5. 简单模仿QQ聊天界面

    首先看一下最终的效果,显示了消息时间,用户昵称,用户头像. 大致实现方法: 用最简单的ListView显示消息内容. 不同的用户使用不同的消息布局文件,从而达到头像左右显示的效果,如上图有2个用户&q ...

  6. Lambda 表达式已阅

    Lambda 表达式已阅 君子之间淡如水,何谓淡如水?并不时常想起,但却无处不在. 背景:This is f**king why we code? 可以让Java 代码异常简洁的Lambda 表达式, ...

  7. [转帖]PG的时间函数使用整理如下

    PG的时间函数使用整理如下 https://blog.csdn.net/dahuzix/article/details/48576945 1.获取系统时间函数 -- :: -- :: -- :: 2. ...

  8. Wait… What Happens When my React Native Application Starts? — An In-depth Look Inside React Native

    Discover how React Native functions internally, and what it does for you without you knowing it. Dis ...

  9. Eureka和ZooKeeper的区别

    首先我们先说下: RDBMS==>(MySql,Oracle,SqlServer等关系型数据库)遵循的原则是:ACID原则(A:原子性.C:一致性.I:独立性.D:持久性.). NoSql==& ...

  10. [转] JS中arr.forEach()如何跳出循环

    我们都知道for循环里要跳出整个循环是使用break,但在数组中用forEach循环如要退出整个循环呢?使用break会报错,使用return也不能跳出循环. 使用break将会报错: var arr ...