Java 自动装箱和拆箱还有包装类的缓存问题

自动装箱和拆箱就是将基本数据类型和包装类之间进行自动的互相转换。JDK1.5 后,
Java 引入了自动装箱(autoboxing)/拆箱(unboxing)。

自动装箱:

基本类型的数据处于需要对象的环境中时,会自动转为"对象"。

我们以 Integer 为例:

在 JDK1.5 以前,这样的代码 Integer i = 5 是错误的,必须要通过 Integer i = new

Integer(5) 这样的语句来实现基本数据类型转换成包装类的过程;

而在 JDK1.5 以后,Java 提供了自动装箱的功能,因此只需 Integer i = 5 这样的语句

就能实现基本数据类型转换成包装类,这是因为 JVM 为我们执行了 Integer i =

Integer.valueOf(5)这样的操作,这就是 Java 的自动装箱。
自动拆箱:

每当需要一个值时,对象会自动转成基本数据类型,没必要再去显式调用 intValue()、

doubleValue()等转型方法。

如 Integer i = 5;int j = i; 这样的过程就是自动拆箱。

我们可以用一句话总结自动装箱/拆箱:

自动装箱过程是通过调用包装类的 valueOf()方法实现的,而自动拆箱过程是通过调用

包装类的 xxxValue()方法实现的(xxx 代表对应的基本数据类型,如 intValue()、

doubleValue()等)。

自动装箱与拆箱的功能事实上是编译器来帮的忙,编译器在编译时依据您所编写的语

法,决定是否进行装箱或拆箱动作。

自动装箱:

java 复制代码
Integer i = 100;//自动装箱
//相当于编译器自动为您作以下的语法编译:
Integer i = Integer. valueOf (100);//调用的是 valueOf(100),而不是 new Integer(100)

自动拆箱:

java 复制代码
Integer i = 100;
int j = i;//自动拆箱
//相当于编译器自动为您作以下的语法编译:
int j = i.intValue();

所以自动装箱与拆箱的功能是所谓的"编译器蜜糖(Compiler Sugar)",虽然使用这

个功能很方便,但在程序运行阶段您得了解 Java 的语义:

包装类空指针异常问题:

java 复制代码
public class Test1 {
    public static void main(String[ ] args) {
        Integer i = null;
        int j = i;
    }
}

null 表示 i 没有指向任何对象的实体,但作为对象名称是合法的(不管这个对象名称存

是否指向了某个对象的实体)。由于实际上 i 并没有指向任何对象的实体,所以也就不可能

操作 intValue()方法,这样上面的写法在运行时就会出现 NullPointerException 错误。

包装类的缓存问题:

整型、char类型所对应的包装类,在自动装箱时,对于-128~127之间的值会进行缓存

处理,其目的是提高效率。

缓存处理的原理为:如果数据在-128~127这个区间,那么在类加载时就已经为该区间

的每个数值创建了对象,并将这256个对象存放到一个名为cache的数组中。每当自动装箱

过程发生时(或者手动调用valueOf()时),就会先判断数据是否在该区间,如果在则直接

获取数组中对应的包装类对象的引用,如果不在该区间,则会通过new调用包装类的构造方法来创建对象。

下面我们以Integer类为例,看一看Java为我们提供的源码,加深对缓存技术的理解:

java 复制代码
public static Integer valueOf(int i) {
if (i >= IntegerCache. low && i <= IntegerCache. high )
return IntegerCache. cache [i + (-IntegerCache. low )];
return new Integer(i);
}

这段代码中我们需要解释下面几个问题:

  1. IntegerCache类为Integer类的一个静态内部类,仅供Integer类使用。

  2. 一般情况下 IntegerCache.low为-128,IntegerCache.high为127,

IntegerCache.cache为内部类的一个静态属性:

java 复制代码
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) {
            try {
                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);
            } catch( NumberFormatException nfe) {
                // If the property cannot be parsed into an int, ignore it.
            }
        }
        high = h;
        cache = new Integer[( high - low ) + 1];
        int j = low ;
        for(int k = 0; k < cache .length; k++)
            cache [k] = new Integer(j++);
            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache. high >= 127;
        }
        private IntegerCache() {}
}

由上面的源码我们可以看到,静态代码块的目的就是初始化数组cache的,这个过程会

在类加载时完成。

下面我们做一下代码测试

包装类的缓存测试:

java 复制代码
public class Test3 {
    public static void main(String[ ] args) {
        Integer in1 = -128;
        Integer in2 = -128;
        System. out .println(in1 == in2);//true 因为 123 在缓存范围内
        System. out .println(in1.equals(in2));//true
        Integer in3 = 1234;
        Integer in4 = 1234;
        System. out .println(in3 == in4);//false 因为 1234 不在缓存范围内
        System. out .println(in3.equals(in4));//true

执行后的结果:

如下是Test3的内存分析:

相关推荐
王夏奇几秒前
python在汽车电子行业中的应用1-基础知识概念
开发语言·python·汽车
He_Donglin1 分钟前
Python图书爬虫
开发语言·爬虫·python
jmxwzy1 分钟前
Redis
数据库·redis·缓存
北辰当尹2 分钟前
【实习之旅】Kali虚拟机桥接模式ping通百度
java·服务器·桥接模式
零叹4 分钟前
Redis热Key——大厂是怎么解决的
数据库·redis·缓存·热key
win x7 分钟前
Redis事务
数据库·redis·缓存
Just Dreamchaser8 分钟前
Pdf和Docx文件导出生成水印工具类
java·给pdf和docx文件添加水印
这个需求做不了10 分钟前
Java实现文件格式转换(图片,视频,文档,音频)
java
星融元asterfusion10 分钟前
AsterNOS SONiC基于YANG模型的现代网络管理:从CLI到gNMI的演进
开发语言·sonic·yang
web3.088899912 分钟前
1688商品详情API接口深度解析
开发语言·python