深入剖析Java中的装箱和拆箱
2016-10-15 20:45
253 查看
Java有八种基本数据类型,Java也为每种基本数据类型都提供了相对应的包装器类型。相信不少学过Java的朋友,也都学过Java的拆装箱机制。出于某种原因,今天我又进一步对Java的拆装箱机制进行了较为深入的研究,记下此文,以便时刻自省。
首先先回顾下Java的八种基本数据类型及对应的包装类:
自动装箱:如上第一行,在执行这行代码时,实际上是在执行Integer i = Integer.valueOf(3);返回给i的,是Integer类型的对象。
自动拆箱:如上第二行,在执行这行代码时,实际上是在执行int k = i.intValue();其中方法intValue()的返回值类
a6e6
型为int。有了这个理论知识,我们看下下面这代码:
好了,自动拆装箱也就到这了,不过,下面的知识点你不能不看,不看你在使用Java的自动拆装箱中会遇坑的。
我们再来看以下常见的关于自动拆装箱的面试题:
i)的源码:
什么,这跟说好的不一样,这是为什么呢,我们还是一样,还看下它执行的源码:
所以,我们可以知道Integer、Short、Byte、Character、Long的实现是类似的,而Float、Double的实现也是类似的。而对于Boolean类型,我们可以想象出来,Boolean的结果不是true,就是false,所以我们根本没必要在自动装箱时为每个对象实例化一个,不过,我们还是要看下源码:
最后,再来看一个比较的问题,这个问题不是两个包装器类型比较,两个数据类类型比较可以也应该用equals()方法。
看以下代码:
好了,今天的分享就到这里了,由于是个人经验总结,难免会出错,欢迎大家批评指正,万般感谢。
首先先回顾下Java的八种基本数据类型及对应的包装类:
基本数据类型 | 长度(字节) | 包装器类型 |
byte | 1 | Byte |
short | 2 | Short |
int | 4 | Integer |
long | 8 | Long |
float | 4 | Float |
double | 8 | Double |
char | 2 | Character |
boolean | 未定 | Boolean |
我们从最经典的int类型开始,先看以下关于拆装箱最常见的例子:
Integer i = 3; int k = i;像以上的代码,其中第一行即为自动装箱,第二行为自动拆箱。
自动装箱:如上第一行,在执行这行代码时,实际上是在执行Integer i = Integer.valueOf(3);返回给i的,是Integer类型的对象。
自动拆箱:如上第二行,在执行这行代码时,实际上是在执行int k = i.intValue();其中方法intValue()的返回值类
a6e6
型为int。有了这个理论知识,我们看下下面这代码:
Integer i = null; int k = i; System.out.println(k);这段代码的执行结果是什么呢?其实通过自动拆箱的知识,我们就知道在第二行代码就会抛出java.lang.NullPointerException异常了,事实上也是如此。
好了,自动拆装箱也就到这了,不过,下面的知识点你不能不看,不看你在使用Java的自动拆装箱中会遇坑的。
我们再来看以下常见的关于自动拆装箱的面试题:
Integer i = 3; Integer j = 3; Integer k = 666; Integer l = 666; System.out.println(i == j); System.out.println(k == l); Integer easy1 = new Integer(3); Integer easy2 = new Integer(3); System.out.println(easy1 == easy2);会输出什么呢?我们知道,==是比较对象的,同一个对象才会使==的结果为true,所以第九行代码的输出明显就是false,那现在的问题就是i与j,k与l是不是同一个对象了,那它们会不会是同一个对象呢,上面说过了,自动装箱实际上执行的是Integer.valueOf(int i),那我们就来看下valueOf方法到底是怎么执行的,以下是Integer.valueOf(int
i)的源码:
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} }我们可以看来,在默认情况下,Java为我们缓存了[-128,127]的对象,所以在这之间,通过自动装箱得到的,是同一个对象,而在这之外的,就不是同一对象了,当然,从代码可以得知,这个缓存的范围是可以改变的。现在,结果就很清楚了:
true false false那么,下面的结果会是什么呢?
Double i = 3.0; Double j = 3.0; Double k = 666.0; Double l = 666.0; System.out.println(i == j); System.out.println(k == l);我们先来看结果吧:
false false
什么,这跟说好的不一样,这是为什么呢,我们还是一样,还看下它执行的源码:
public static Double valueOf(double d) { return new Double(d); }我们可以看得出来,Double.valueOf方法并没有像Integer的实现一样,只是简单的返回一个新的对象,为什么会是这样呢,其实这也很好想象,因为Integer是整型,是有限个数的,而浮点型是非有限的。
所以,我们可以知道Integer、Short、Byte、Character、Long的实现是类似的,而Float、Double的实现也是类似的。而对于Boolean类型,我们可以想象出来,Boolean的结果不是true,就是false,所以我们根本没必要在自动装箱时为每个对象实例化一个,不过,我们还是要看下源码:
public static Boolean valueOf(String s) { return toBoolean(s) ? TRUE : FALSE; }
public static final Boolean TRUE = new Boolean(true); public static final Boolean FALSE = new Boolean(false);刚好,实现正是我们所想的。
最后,再来看一个比较的问题,这个问题不是两个包装器类型比较,两个数据类类型比较可以也应该用equals()方法。
看以下代码:
Integer e1 = 666; System.out.println(e1 == 666);这里会输出什么呢?其实这个问题就在于,基本数据类型与对应的类类型比较时,是自动拆箱后比较,还是自动装箱后比较?我们在第二行代码处打一个断点,然后debug模式运行:
public int intValue() { return value; }我们看到,程序调用了intValue()方法,也就拆箱后比较,也就是666==666,结果当然是true了。这也说明了基本数据类型与对应的类类型比较时,是类类型拆箱后比较,即比较的是数值,不过这样我们就要当心了,当类类型为null时,可是会出现空指针异常的喔。
好了,今天的分享就到这里了,由于是个人经验总结,难免会出错,欢迎大家批评指正,万般感谢。
相关文章推荐
- 【装箱拆箱】java自动 深入剖析
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- java自动装箱拆箱深入剖析
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- java自动装箱拆箱深入剖析
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 【转】深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- java 深入剖析Java中的装箱和拆箱(Autoboxing/unboxing)
- 深入剖析Java中的装箱和拆箱
- 深入剖析Java中的装箱和拆箱
- 从别人那淘的知识 深入剖析Java中的装箱和拆箱