Java 装箱与拆箱

  以前在用包装类的时候从来都不会关心里面的具体实现,只是感觉从基本类型一下子就到了类对象真神奇。今天参考了海子的博客[1],决定对包装类进行下系统的认识。

一、什么是包装类?包装类和基本类型相互赋值会有什么动作发生?

  众所周知,Java有8种基本类型,为了面向对象的需要为这八种类型各自都设计对应的包装类型。比如int  对应的 Integer。

  如果要生成一个值为20的Integer有以下两种写法:

  

Integer i=new Integer(20);
Integer i2=20;

  第一种是普通的新建对象,第二种采用的是直接赋值。这两种写法会产生不同的动作,稍后再说。

  这里需要关注的是第二种,用赋值号“=”将根据int值创建对应的Integer对象,这就是装箱。

  那么什么是拆箱呢?

  

int i3=i2;

  用"="将Integer对象复制给int类型变量,就是拆箱。

二、拆箱与装箱是怎么实现的

  这里面用了个例子

  

public class Main {
    public static void main(String[] args) {
        Integer integer=10;
        int i=integer;
    }
}

通过反编译后得到下面的内容

  从反编译的结果可以看出Integer的装箱用了Integer.valueOf   而拆箱用了Integer.intValue。

  因此可以用一句话总结装箱和拆箱的实现过程:

  装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。

  之前一直没怎么注意这个细节,在将字符串转换成int型的时候,preseInt和valueOf混用,以后得注意了要用parseInt.

三、包装类的分析

  1>包装类可以分为三种

  1、包装类中Character,Byte,Short ,Integer,Long 是类似的,他们有一个很大的共同点就是都有对应的Cache。其大小和范围如下:

类名 大小 范围
Byte 128 0~127
Character 256 -128~127
Short 256 -128~127
Integer 256 -128~127
Long 256 -128~127

  这些Cache都在static块中实现的,在包装类被加载的时候即被创建,这些被创建的对象保存在堆中,引用保存在常量池中,当通过装箱新建一个包装类时,会进行判断假如在范围内的直接返回该数值对应的包装类的对象,否则新建。

  类如:

  

        Character c1=‘A‘;
        Character c2=‘A‘;
        Character c3=new Character(‘A‘);
        System.out.println(c1==c2);
        System.out.println(c2==c3);

  输出是true  false  即通过装箱得到的包装类对象会执行上述动作,而通过new创建的对象不会。

  

        Character c1=128;
        Character c2=128;
        System.out.println(c1==c2);

  这里输出的是false  即在范围之外的直接新建对象,并返回对象引用。

  2、Float,Double这两个包装类没有对应的Cache,那么每次装箱都会新建一个对象

  

        Double d1=128.0;
        Double d2=128.0;
        System.out.println(d1==d2);

  输出是false    ,Float类型也是一样

  3、Boolean

  Boolean默认创建了两个Boolean对象TRUE和FALSE。

  

 public static final Boolean TRUE = new Boolean(true);

    /**
     * The <code>Boolean</code> object corresponding to the primitive
     * value <code>false</code>.
     */
    public static final Boolean FALSE = new Boolean(false);

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

  这样只要逻辑上相同,则对应的包装类对象是相同的。

  2>Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。

  当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:

  1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;

  2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。

  3>编译器的处理

  这里引用海子的例子并稍加修改,有兴趣的朋友直接点击下面的链接前往原文。

  

    public static void main(String[] args) {
          int i=1;
          Integer a = 1;
          Integer b = 2;
          Integer c = 3;
          Integer d = 3;
          Integer e = 321;
          Integer f = 321;
          Long g = 3L;
          Long h = 2L;
          Long k=new Long(2L);

          System.out.println(i==a);//1
          System.out.println(c==d);//2
          System.out.println(e==f);//3
          System.out.println(c==(a+b));//4
          System.out.println(c.equals(a+b));//5
          System.out.println(g==(a+b));//6
          System.out.println(g.equals(a+b));//7
          System.out.println(g.equals(a+h));//8
          System.out.println(k.equals(a+h));//9
    }

  当"=="两边都是包装类引用时,会直接判断是不是同一对象,即地址是否相同;假如一边是基本类型,一边是包装类对象时,那么会使用xxxValue进行拆箱,对数值进行比较,;当一边出现运算符时,同样也是进行拆箱,对数值进行比较。

  当使用的是equals,则会先对表达式进行运算,然后进行装箱,(不会进行类型转换),判断是否同一对象。

  上面的输出是:

true    //1
true  //2
false   //3
true    //4
true   //5
true   //6
false  //7
true   //8
false   //9

  第一个,一边是基本类型一边是包装对象,进行拆箱进行比较数值   true

  第二个,第三个参考上面,也好理解

  第四个 右边有运算符,进行拆箱比较数值  true

  第五个用的是equals  ,现将a和b拆箱进行数值相加得到3,然后将3装箱,与c进行比较,由于在范围内所以是true;

  第六个  两边都进行拆箱,进行数值比较

  第七个  一边是Long  一边是Integer   不等

  第八个   右边在进行算术运算时将int转换成long,最后装箱  都是long  ,且在范围内。

  第九个   k是直接创建的对象,肯定和其他的不是同一对象。

[1]本文参考:http://www.cnblogs.com/dolphin0520/p/3780005.html

时间: 2024-11-08 10:29:49

Java 装箱与拆箱的相关文章

java 装箱和拆箱

每次看到某篇博客里面说要静下心来欣赏源码,我都很感慨,我的耐心没人家好.是真的要静下心来读源码,因为说不定就像作者说的那样 “说不定你就发现了一个优秀的设计呢!!!” 才不久就被同事说了,学知识的时候不要看野史,要看官方.我还是做不到.官方是一定要看的,但是野史还是照样翻,因为我觉得很多野史写的很生动,甚至有滋有味,有声有色,能从作者的言词中感受到人家的认真,不知不觉中能成为自己的榜样. 都是同行,为什么人家就能那么优秀,我要向其学习. 题外话 今天早上在学习公司代码,然后准备学习下MVP框架,

JAVA——装箱和拆箱

Java 将某些基本数据类型自动转换为包装类型的过程称为装箱,相反自动将包装类型转换为基本数据类型的过程称为拆箱. Integer integer_1=1; //装箱 int i=integer_1; //拆箱 装箱会调用 Integer.valueOf(int) 函数: 拆箱会调用 Integer.intValue(Integer) 函数 几个面试中会经常遇到的问题: 先来看一段代码: 这段代码的输出结果是: 对于第一行和第二行,因为装箱会调用vlueOf(),我们来看看这个函数的源码: 1

Java 装箱、拆箱 包装器

先说java的基本数据类型.java基本数据类型:byte.short.int.long.float.double.char.boolean 基本数据类型的自动装箱(autoboxing).拆箱(unboxing)是自J2SE 5.0开始提供的功能.装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质.int包装成Integer.float包装成Float拆箱:和装箱相反,将引用类型的对象简化成值类型的数据 说明:equals() 比较的是两个对象的值(内容)是否相同.对不同类型的对

java装箱跟拆箱解析

/** * 在jdk1.5之后,java为基本数据类型到对应的应用数据类型提供了自动拆箱装箱操作 * 不管是自动拆箱还是自动装箱都是应用数据类型有的方法,基本数据类型是没有任何方法可调用的 *从概念上来说,拆箱即从应用数据类型到基本数据类型,装箱即从基本数据类型到应用数据类型 */ //进行了自动装箱操作,实际是:Integer i1 = Integer.valueOf(100); //valueOf方法当值在-128到127之间时会去缓存中取对象,如果缓存中不存在则创建,如果存在则不创建直接取

深入剖析Java中的装箱和拆箱

阅读目录 一.什么是装箱?什么是拆箱?二.装箱和拆箱是如何实现的三.面试中相关的问题 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 回到顶部 一.什么是装箱?什么是拆箱? 我们知道 Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE5之前,如果要生成

《Java中的自动装箱和拆箱功能.》

1 //Java中的自动装箱和拆箱功能. 2 class AutoboxingUnboxing 3 { 4 public static void main(String[] args) 5 { 6 //直接把一个基本类型变量赋给Interger对象. 7 Integer inObj = 5; 8 Object inObj1 = 6; 9 //直接把一个boolean类型的变量赋给一个Object类型的变量. 10 Object boolObj = true; 11 //直接把Integer对象赋

Java中的装箱与拆箱

在J2SE5.0后推出了自动装箱和拆箱的功能,以提高我们的开发效率,然而自动装箱和拆箱实际上是通过编译器来支持的(并非语言本身,或者说虚拟机),因而这种支持也隐藏了部分内部实质,再加上某些类的优化(比如Integer里面的缓存等,参看关于缓存节),就更加容易在特定的环境下产生问题,并且如果不知道原来还无法调试.以下先是简单的介绍了编译器对装箱和拆箱的实现,并根据实现简单介绍一下可能会遇到的几个问题. 在Java SE5之前,如果要生成一个数值为10的Integer对象,必须这样进行: Integ

Java的自动拆箱和装箱

Java 1.5中引入了自动装箱和拆箱机制 自动装箱:(看代码) <span style="font-family:SimSun;font-size:18px;color:#000000;">//自动装箱:把基本类型用它们所对应的引用类型包装起来,使它们具有对象的属性 Integer integer_a = 8; </span> 自动拆箱:(看代码) <span style="font-family:SimSun;font-size:18px;c

深入剖析Java中的装箱和拆箱(转)

自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱.拆箱相关的问题. 以下是本文的目录大纲: 一.什么是装箱?什么是拆箱? 二.装箱和拆箱是如何实现的 三.面试中相关的问题 一.什么是装箱?什么是拆箱? 在前面的文章中提到,Java为每种基本数据类型都提供了对应的包装器类型,至于为什么会为每种基本数据类型提供包装器类型在此不进行阐述,有兴趣的朋友可以查阅相关资料.在Java SE