Java装箱和拆箱的基本概念及使用

要理解装箱和拆箱的概念,就要理解Java数据类型

装箱:把基本类型用它们相应的引用类型包装起来,使其具有对象的性质。int包装成Integer、float包装成Float

拆箱:和装箱相反,将引用类型的对象简化成值类型的数据

Integer a = 100;                  这是自动装箱  (编译器调用的是static Integer valueOf(int i))
int     b = new Integer(100); 这是自动拆箱

看下面一段代码

m1

public class DataType {
 
    public static void main(String args[]) {
        DataType dt = new DataType();
        dt.m11();
        dt.m12();
         
    }
 
    public void m11() {
        Integer a = new Integer(100);
        Integer b = 100;
        System.out.println("m11 result " + (a == b));
    }
 
    public void m12() {
        Integer a = new Integer(128);
        Integer b = 128;
        System.out.println("m12 result " + (a == b));
    }
 
     
}

  打印结果是什么?

m11 result false
m12 result false

“==”比较的是地址,而a和b两个对象的地址不同,即是两个对象,所以都是false

通过javap解析字节码,内容如下

public void m11();
  Code:
   0:   new     #44; //class java/lang/Integer
   3:   dup
   4:   bipush  100
   6:   invokespecial   #46; //Method java/lang/Integer."<init>":(I)V
   9:   astore_1
   10:  bipush  100
   12:  invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
teger;
   15:  astore_2
   16:  getstatic       #53; //Field java/lang/System.out:Ljava/io/PrintStream;
   19:  new     #59; //class java/lang/StringBuilder
   22:  dup
   23:  ldc     #61; //String m11 result
   25:  invokespecial   #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
ng/String;)V
   28:  aload_1
   29:  aload_2
   30:  if_acmpne       37
   33:  iconst_1
   34:  goto    38
   37:  iconst_0
   38:  invokevirtual   #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
   41:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
   44:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   47:  return
 
public void m12();
  Code:
   0:   new     #44; //class java/lang/Integer
   3:   dup
   4:   sipush  128
   7:   invokespecial   #46; //Method java/lang/Integer."<init>":(I)V
   10:  astore_1
   11:  sipush  128
   14:  invokestatic    #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
teger;
   17:  astore_2
   18:  getstatic       #53; //Field java/lang/System.out:Ljava/io/PrintStream;
   21:  new     #59; //class java/lang/StringBuilder
   24:  dup
   25:  ldc     #82; //String m12 result
   27:  invokespecial   #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
ng/String;)V
   30:  aload_1
   31:  aload_2
   32:  if_acmpne       39
   35:  iconst_1
   36:  goto    40
   39:  iconst_0
   40:  invokevirtual   #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
ng/StringBuilder;
   43:  invokevirtual   #70; //Method java/lang/StringBuilder.toString:()Ljava/l
ang/String;
   46:  invokevirtual   #74; //Method java/io/PrintStream.println:(Ljava/lang/St
ring;)V
   49:  return

 m2

public class DataType {
 
    public static void main(String args[]) {
        DataType dt = new DataType();
        dt.m21();
        dt.m22();
    }
 
    public void m21() {
        Integer a = new Integer(100);
        Integer b = new Integer(100);
        System.out.println("m21 result " + (a == b));
    }
 
    public void m22() {
        Integer a = new Integer(128);
        Integer b = new Integer(128);
        System.out.println("m22 result " + (a == b));
    }
 
     
}

  打印结果是

m21 result false
m22 result false

a和b仍是两个对象

javap解析内容

  1. public void m21();
    Code:
    0: new #44; //class java/lang/Integer
    3: dup
    4: bipush 100
    6: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
    9: astore_1
    10: new #44; //class java/lang/Integer
    13: dup
    14: bipush 100
    16: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
    19: astore_2
    20: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    23: new #59; //class java/lang/StringBuilder
    26: dup
    27: ldc #84; //String m21 result
    29: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    32: aload_1
    33: aload_2
    34: if_acmpne 41
    37: iconst_1
    38: goto 42
    41: iconst_0
    42: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    45: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    48: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    51: return
  2.  
  3. public void m22();
    Code:
    0: new #44; //class java/lang/Integer
    3: dup
    4: sipush 128
    7: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
    10: astore_1
    11: new #44; //class java/lang/Integer
    14: dup
    15: sipush 128
    18: invokespecial #46; //Method java/lang/Integer."<init>":(I)V
    21: astore_2
    22: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    25: new #59; //class java/lang/StringBuilder
    28: dup
    29: ldc #86; //String m22 result
    31: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    34: aload_1
    35: aload_2
    36: if_acmpne 43
    39: iconst_1
    40: goto 44
    43: iconst_0
    44: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    47: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    50: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    53: return

m3

public class DataType {
 
    public static void main(String args[]) {
        DataType dt = new DataType();
        dt.m31();
        dt.m32();
    }
 
    public void m31() {
        Integer a = 100;
        Integer b = 100;
        System.out.println("m31 result " + (a == b));
    }
 
    public void m32() {
        Integer a = 128;
        Integer b = 128;
        System.out.println("m32 result " + (a == b));
    }
 
 
}

  打印结果

m31 result true
m32 result false

为什么有第一个是true,第二个是false呢?观察javap解析的数据

javap解析内容

  1. public void m31();
    Code:
    0: bipush 100
    2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    5: astore_1
    6: bipush 100
    8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    11: astore_2
    12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    15: new #59; //class java/lang/StringBuilder
    18: dup
    19: ldc #88; //String m31 result
    21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    24: aload_1
    25: aload_2
    26: if_acmpne 33
    29: iconst_1
    30: goto 34
    33: iconst_0
    34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    43: return
  2.  
  3. public void m32();
    Code:
    0: sipush 128
    3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    6: astore_1
    7: sipush 128
    10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    13: astore_2
    14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    17: new #59; //class java/lang/StringBuilder
    20: dup
    21: ldc #90; //String m32 result
    23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    26: aload_1
    27: aload_2
    28: if_acmpne 35
    31: iconst_1
    32: goto 36
    35: iconst_0
    36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    45: return

m4

public class DataType {
 
    public static void main(String args[]) {
        DataType dt = new DataType();
        dt.m41();
        dt.m42();
    }
 
 
    public void m41() {
        Integer a = Integer.valueOf(100);
        Integer b = 100;
        System.out.println("m41 result " + (a == b));
    }
     
    public void m42() {
        Integer a = Integer.valueOf(128);
        Integer b = 128;
        System.out.println("m42 result " + (a == b));
    }
}

  打印结果

m41 result true
m42 result false

javap解析内容

  1. public void m41();
    Code:
    0: bipush 100
    2: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    5: astore_1
    6: bipush 100
    8: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    11: astore_2
    12: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    15: new #59; //class java/lang/StringBuilder
    18: dup
    19: ldc #92; //String m41 result
    21: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    24: aload_1
    25: aload_2
    26: if_acmpne 33
    29: iconst_1
    30: goto 34
    33: iconst_0
    34: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    37: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    40: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    43: return
  2.  
  3. public void m42();
    Code:
    0: sipush 128
    3: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    6: astore_1
    7: sipush 128
    10: invokestatic #49; //Method java/lang/Integer.valueOf:(I)Ljava/lang/In
    teger;
    13: astore_2
    14: getstatic #53; //Field java/lang/System.out:Ljava/io/PrintStream;
    17: new #59; //class java/lang/StringBuilder
    20: dup
    21: ldc #94; //String m42 result
    23: invokespecial #63; //Method java/lang/StringBuilder."<init>":(Ljava/la
    ng/String;)V
    26: aload_1
    27: aload_2
    28: if_acmpne 35
    31: iconst_1
    32: goto 36
    35: iconst_0
    36: invokevirtual #66; //Method java/lang/StringBuilder.append:(Z)Ljava/la
    ng/StringBuilder;
    39: invokevirtual #70; //Method java/lang/StringBuilder.toString:()Ljava/l
    ang/String;
    42: invokevirtual #74; //Method java/io/PrintStream.println:(Ljava/lang/St
    ring;)V
    45: return
  4.  
  5. }

分析

javap是Java自带的一个工具,可以反编译,也可以查看Java编译器生成的字节码(上面代码只使用了javap -c DataType),是分析代码的一个好工具,具体怎么使用请Google一下

先看一下m4,为什么运行结果中出现了“true”呢,true说明a、b是同一个对象。 

但a对象是调用Integer.valueOf()生成的,b是通过自动装箱生成的对象,为什么会是同一个对象呢?再看一下字节码吧,毕竟Java程序是依靠虚拟机运行字节码实现的。

m41这个方法只适用了一次valueOf(),但字节码中出现了两次,说明自动装箱时也调用了valueOf()。

下面是valueOf()具体实现

/**
 * Returns a <tt>Integer</tt> instance representing the specified
 * <tt>int</tt> value.
 * If a new <tt>Integer</tt> instance is not required, this method
 * should generally be used in preference to the constructor
 * {@link #Integer(int)}, as this method is likely to yield
 * significantly better space and time performance by caching
 * frequently requested values.
 *
 * @param  i an <code>int</code> value.
 * @return a <tt>Integer</tt> instance representing <tt>i</tt>.
 * @since  1.5
 */
public static Integer valueOf(int i) {
final int offset = 128;
if (i >= -128 && i <= 127) { // must cache
    return IntegerCache.cache[i + offset];
}
    return new Integer(i);
}

在【-128,127】之间的数字,valueOf返回的是缓存中的对象,所以两次调用返回的是同一个对象。  

【参考】http://jzinfo.iteye.com/blog/450590

    http://xiaoyu1985ban.iteye.com/blog/1384191

Java装箱和拆箱的基本概念及使用的更多相关文章

  1. 1.1 JAVA装箱和拆箱以及Java Number & Math&Character 类

    JAVA装箱和拆箱 从Java SE5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要这样就可以了.原文链接: http://www.cnblogs.com/dolph ...

  2. Java 装箱和拆箱

    1.装箱机制 基础类型引用到其包装类型,这样就可以调用其各种方法. 例如,我们声明: Integer a = 1; 其在编译过程中会自动解释成: Integer a = Integer.valueOf ...

  3. java装箱跟拆箱解析

    /** * 在jdk1.5之后,java为基本数据类型到对应的应用数据类型提供了自动拆箱装箱操作 * 不管是自动拆箱还是自动装箱都是应用数据类型有的方法,基本数据类型是没有任何方法可调用的 *从概念上 ...

  4. JAVA——装箱和拆箱

    Java 将某些基本数据类型自动转换为包装类型的过程称为装箱,相反自动将包装类型转换为基本数据类型的过程称为拆箱. Integer integer_1=1; //装箱 int i=integer_1; ...

  5. Java 装箱、拆箱 包装器

    先说java的基本数据类型.java基本数据类型:byte.short.int.long.float.double.char.boolean 基本数据类型的自动装箱(autoboxing).拆箱(un ...

  6. Java装箱和拆箱

    https://www.cnblogs.com/dolphin0520/p/3780005.html http://mxdxm.iteye.com/blog/2028196 装箱过程是通过调用包装器的 ...

  7. java和c#中的装箱和拆箱操作

    c#装箱和拆箱 装箱:整体上来说,装箱是将值类型转换成引用类型,比如将Vector3转换成Object类型. 具体而言: 1)在托管堆中为值类型分配内存.除了原始的数值以外还应该有指向该数值的引用. ...

  8. Java暗箱操作之自动装箱与拆箱

    我以前在写Android项目的时候,估计写得最多最熟练的几句话就是: List<Integer> list = new ArrayList<Integer>(); list.a ...

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

    深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来一些看一下装箱和拆箱中的若干问题.本文先讲述装箱和拆箱最基本的东西,再来看一下面试笔试中经常遇到的与装箱 ...

随机推荐

  1. $BZOJ3232$ 圈地游戏 网络流

    正解:最小割+01分数规划 解题报告: 传送门$QwQ$ 感$jio$这个好像是$NOIp2018$集训的时候$cjk$学长讲01分数规划的时候港的,,,?$QwQ$虽然我还是不会嘤 首先看到这个分数 ...

  2. $[NOIp2015]$ 子串 $dp$

    \(Sol\) 不知道为啥看起来就很\(dp\)的亚子.我们关心的只有\(A\)串当前用到哪一个,\(B\)串已经匹配到哪个位置,已经匹配的被分成了多少段.所以设\(f_{i,j,k,0/1}\)表示 ...

  3. $Noip2014/Luogu1351$ 联合权值 树形

    $Luogu$ $Description$ 给定一棵树,每两个距离为$2$的点之间可以产生"联合权值","联合权值"定义为这两个数的乘积.求最大的联合权值以及所 ...

  4. Python3 虚拟开发环境搭建

    虚拟环境的搭建 优点 1.使不同应用开发环境相互独立 2.环境升级不影响其他应用,也不会影响全局的python环境 3.防止出现包管理混乱及包版本冲突 windows 安装 # 建议使用pip3安装到 ...

  5. Ceph14.2.5 RBD块存储的实战配置和详细介绍,不看后悔! -- <3>

    Ceph RBD介绍与使用 RBD介绍 RBD即RADOS Block Device的简称,RBD块存储是最稳定且最常用的存储类型.RBD块设备类似磁盘可以被挂载. RBD块设备具有快照.多副本.克隆 ...

  6. spring boot使用拦截器

    1.编写一个拦截器 首先,我们先编写一个拦截器,和spring mvc方式一样.实现HandlerInterceptor类,代码如下 package com.example.demo.intercep ...

  7. vue传值(父子传值,非父子传值)

    vue组件传值,分为父子传值和非父子传值,父子传值又分为父传子和子传父. 组件之间的传值,实现了数据的联动,是从操作Dom到操作数据一个跳转性的突破,在学习vue双向绑定原理之后, 这种观念就应该继续 ...

  8. TensorFlow——Graph的基本操作

    1.创建图 在tensorflow中,一个程序默认是建立一个图的,除了系统自动建立图以外,我们还可以手动建立图,并做一些其他的操作. 下面我们使用tf.Graph函数建立图,使用tf.get_defa ...

  9. Tarjan强连通分量模板

    最好还是看一看下面这个网址吧 我的这篇博客里的代码更加缜密(毫无错误的神级代码)https://www.cnblogs.com/Tidoblogs/p/11315153.html https://ww ...

  10. 我怎么感觉 ConcurrentDictionary<,> 不是线程安全的喃?

    直接上代码 class Program { static readonly ConcurrentDictionary<string, Person> Dic = new Concurren ...