关闭

JavaSE的自动装箱和自动拆箱

标签: javajava se
631人阅读 评论(0) 收藏 举报
分类:

回顾一下Java基础数据类型:

Java数据类型

基础类型 字节 包装类型
int 4字节 Integer
byte 1字节 Byte
short 2字节 Short
long 8字节 Long
float 4字节 Float
double 8字节 Double
char 2字节 Character
boolean 未定 Boolean

Java属于面向对象语言那么为什么会出现非对象类型数据(基础类型),因为基础数据类型是的虚拟机的运行速度更快而且占用内存更少。详情内容可以参见:Java为什么需要保留基本数据类型

为什么要有装箱&拆箱

在JavaSE5之前我们创建爱你Integer对象:

Integer i = new Integer(10);

从JavaSE5提供了自动装箱的特性时,我们可以更简单的创建基础类型的对象:

Integer a = 10;
int b = a;

从上面的代码我们可以简单的看出装箱、拆箱的操作:
Integer a = 10; 我们将10【装箱】生成Integer对象。
int b = a; 我们将Integer【拆箱】转成int基础类型

装箱和拆箱是如何实现的

我们这里先写一个简单的类,然后反编译看看它的字节码文件

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

反编译出来的字节码文件:

Main字节码.jpg

结论:

装箱操作:

Integer a = 10;
//实际执行的是Integer a = Integer.valueOf(10);

拆箱操作:

int b = a;
//实际执行的是int b = a.intValue();

其他&扩展

我们先来看一道面试题:

public class Main {
    public static void main(String[] args) {
        Integer a = 10;
        Integer b = 10;
        Integer c = 128;
        Integer d = 128;
        System.out.println(a == b);
        System.out.println(c == d);
    }
}

内心怀揣自己的真是答案,我们看看下边的源代码:
先看看Integer装箱和拆箱的函数源码:

/**
 * Returns the value of this {@code Integer} as an
 * {@code int}.
 */
public int intValue() {
    return value;
}

/**
 * Returns an {@code Integer} instance representing the specified
 * {@code int} value.  If a new {@code Integer} 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.
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
  • 拆箱操作:直接返回Integer内的数值
  • 装箱操作:在i大于IntegerCache.low或者i小于IntegerCache.high时返回缓存的Integer对象,否则创建新的Integer对象。
/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */
private static class IntegerCache {
    /*********/
}

通过源码码我们可以发现,Integer在数据为[-128,127]之间时。使用了IntegerCache 返回缓存中对象的引用,否则new一个新的对象。

看到上面这个答案,有些同学就会想到:除过Integer之前还有其他的基础数据类型,那么其他的类型是否也是专业那个的呢?答案:是也不是。原理想想大家也都明白:

  • Boolean内部有true&false两个静态变量,最后装箱得到的值都是这两个静态变量的引用。
  • Long&Integer&Short&Byte在数值为[-128,127]之间都有Cache。
  • Double&Float则都没有。

所以上面问题的正确答案分别是:true、false。

见识了”==”比较,现在看equals比较结果:
同样我们也先看一道题目:

public class Main {
    public static void main(String[] args) {
        Integer a = 1;
        Integer b = 2;
        Long c = 3L;
        System.out.println(c == (a + b));
        System.out.println(c.equals(a + b));
    }
}

然后我们再看看源码:

/**
 * Compares this object to the specified object.  The result is
 * {@code true} if and only if the argument is not
 * {@code null} and is an {@code Integer} object that
 * contains the same {@code int} value as this object.
 *
 * @param   obj   the object to compare with.
 * @return  {@code true} if the objects are the same;
 *          {@code false} otherwise.
 */
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

在Java中我们知道操作”==”的两个数都是数据包装类型对象的引用的话,那么则是用来比较两个引用所指向的对象是不是同一个;而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。为什么呢,因为”==”两边引用数据类型必须一致,要不然无语错误。

所以我们得到上边题目的答案是:true、false。
因为第一次比较实际是先对数据进行拆箱然后比较,所以得到的结果是true;第二次比较实际是先拆箱(两个Integer对象拆箱)后装箱(将拆箱且计算后的数据再装箱),然后同Long对象比较,显然不是同一类型所以得到false。

以上问题及答案都是作者亲自敲出来的,想实际操作同学也可以反编译class文件看看【真相】。

想阅读作者的更多文章,可以查看我的公共号:

振兴书城

0
0
查看评论

自动装箱和自动拆箱(AutoBoxing,Unboxing)

什么是自动装箱拆箱 基本数据类型的自动装箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0开始提供的功能。  一般我们要创建一个类的对象实例的时候,我们会这样:  Class a = new Class(parameter);  当我们创...
  • u013078669
  • u013078669
  • 2016-10-09 13:38
  • 1462

跟着小白浅谈"自动装箱及自动拆箱"

自动装箱及自动拆箱篇:     今天小白和大家们谈谈什么是自动装箱及自动拆箱,那么什么是自动装箱和拆箱了? 其实就是包装类(wrapper)提供的一种机制自动装箱(autoboxing)自动拆箱(unboxing)该功能是j2se.5.0提供的,里面有基本数据类型所对应很多是时...
  • qq1723205668
  • qq1723205668
  • 2016-06-05 13:50
  • 1117

自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)

JDK1.5提供了自动装箱(Autoboxing)和自动拆箱(AutoUnboxing)功能。 所谓自动装箱,就是可以把一个基本类型变量直接赋给对应的包装类变量,或者赋给Object变量(Object类是所有类的父类,子类对象可以直接赋给父类变量); 自动拆箱则与之相反,允许直接把包装类对象直接...
  • zlz18225318697
  • zlz18225318697
  • 2016-09-20 09:11
  • 567

Java进阶之自动拆箱与自动装箱

自动装箱:把基本类型用它们对应的包装类包装起来,使它们具有对象的特质,可以调用所对应的包装类所定义的方法,比如toString()等。 自动拆箱:跟自动装箱的方向相反,将Integer及Double这样的包装类的对象重新简化为基本类型的数据。
  • qq_31655965
  • qq_31655965
  • 2016-06-06 18:04
  • 1697

Integer的自动拆箱和自动装箱的陷阱(整型数-128到127的值比较问题)

原文地址:http://blog.csdn.net/ma451152002/article/details/9076793 Integer的自动拆装箱的陷阱(整型数-128到127的值比较问题): 1、先看下面的例子: [java] view plain...
  • tanga842428
  • tanga842428
  • 2016-10-11 17:08
  • 1186

Java自动装箱和自动拆箱

Java自动装箱和拆箱
  • liamao16
  • liamao16
  • 2016-04-27 08:59
  • 882

jdk1.5新特性之自动装箱与拆箱

Jdk1.5新特性之自动装箱与拆箱 Jdk1.5出现了很多新特性,其中一个是自动装箱与拆箱。 谈到自动装箱和拆箱,就不得不说java基本类型的包装类。 1.基本类型的包装器类:  我们都知道java是面向对象的编程语言,不过它包含8种基本数据类型,8个基本数据类型不支持面向对象编程...
  • javawcj123
  • javawcj123
  • 2015-08-07 20:02
  • 512

自动装箱和拆箱原理简析

自动装箱和拆箱是jdk1.5引入的特性基本类型:boolean byte char short int long float double;基本类型包装类:Boolean Byte Character Short Integer Long Float Double自动装箱,指在基本数据类型值和其对...
  • angel1hao
  • angel1hao
  • 2016-07-21 15:36
  • 1544

自动拆箱&自动装箱以及String 和基本数据类型封装类生成的对象是否相等

自动拆箱(unboxing)&自动装箱(boxing) @author 李东秀|| qq:1028659927 本文主要为自己理解所做的学习笔记,如有不对的地方, 望各位看官不吝指出,代码运行环境:Ubuntu 14.04,jdk1.7版本    ...
  • u010126792
  • u010126792
  • 2017-03-12 13:14
  • 602

【Java】Java的==和equals()以及自动装箱拆箱

Java的==和equals()以及自动装箱拆箱Java的和equals以及自动装箱拆箱 抛一个问题 先说一说 和 equals方法equals方法 再说一下Integer的缓存机制 自动装箱和自动拆箱 自动装箱 自动拆箱 再来看之前那个问题就很简单了抛一个问题大家先看下面的代码,先不要看答案自己...
  • cflys
  • cflys
  • 2017-07-22 11:02
  • 357
    个人资料
    • 访问:288693次
    • 积分:3978
    • 等级:
    • 排名:第9390名
    • 原创:329篇
    • 转载:17篇
    • 译文:10篇
    • 评论:35条
    博客专栏
    最新评论