Java基础之包装类的自动装箱和拆箱详解

来源:互联网 发布:稳定的网络怎么 编辑:程序博客网 时间:2024/06/05 17:14

定义

在java中,数据类型可以分为两大类,即基本数据类型和引用数据类型,基本数据类型的数据不是对象,所以对于要将数据类型作为对象来使用的情况,java提供了相对应的包装类。(关于包装类的详细介绍请参看博客Java基础之常用类详解)

本篇博客主要讲述包装类的自动装箱和拆行机制。

所谓装箱,就是把基本数据类型用它们相对应的引用类型包起来,使它们可以具有对象的特质,如我们可以把int类型包装成Integer类型的对象,或者把double包装秤Double,等等。

所谓拆箱,就是和装箱的方向相反,将Integer即Double这样的引用类型的对象重新简化成基本数据类型的数据。

而java JDK引入的自动装箱和拆箱就是编译器来依据我们编写的代码,决定是否进行装箱和拆箱动作。即无需使用valueOf()和intValue()等方法。(如果这方面不熟悉请参看博客Java基础之常用类详解)

关于自动装箱拆箱机制的注意事项

这是本篇博客要讲述的重点

先看一个小例子:

public class WrapperText {    public static void main(String[] args) {        Integer a = 100;        Integer b = 100;        Integer c = 200;        Integer d = 200;        System.out.println(a == b);//1        System.out.println(a == 100);//2        System.out.println(c == d);//3        System.out.println(c == 200);//4    }}

如果我们对于Java中自动装箱和拆箱操作了解不够深入的话,一定会这么想:自动装箱后,abcd都是Integer对象的不同引用,“==”操作符又是用来比较对象引用的,所以1和3都应输出false。而对于2和4,由于a和c都进行了自动拆箱,因此其比较是基本数据类型的比较。“==”操作符比较的使它们的值,所以2和4因该输出true。即最终结果输出:
false
true
false
true
但是正确的结果却是:
这里写图片描述
我们看到1的结果为true,3的结果为false,这是为什么呢。其实很简单,自动装箱过程其实是调用了valueOf()的方法,而valueOf()方法的源码为:

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内部为了节省内存,IntegerCache类中有一个数组缓存了值从-128到127的Integer对象。当我们调用Integer.valueOf(int i)的时候,如果i的值时结余-128到127之间的,会直接从这个缓存中返回一个对象,否则就new一个新的Integer对象。因此,1为true,3为false。

最后分享一道与之相关的很有意思的题目:

请提供一个对i的声明,将下面的循环转变成为一个无限循环:

while(j <= i && i <= j && i != j){    }

相信如果仔细阅读了本篇博客,这道题一定能够很轻松的解决。

1 0