Java中Integer类的“坑”,你是否也踩了?

一、问题

一段代码引发的血案

为了让int类型的方法参数可以接收null值,通常我们会把设置成int类型的包装类型Integer,我们的故事便从这里开始,我们先来看一段代码:

public class Demo {

    public static void main(String[] args) {
        test(10,10);
        test(128,128);
    }
    public static void test(Integer i,Integer j){
        if(i == null || j == null){
            return;
        }
        if(i == j){
            System.out.println("成功!");
        }else {
            System.out.println("失败!");
        }
    }
}

控制台输出:

成功!
失败!

My God,为什么第2个输出失败,而不是成功!崩溃。。。。

二、原因

猜测

我们猜测是Integer类导致的,我们知道Integer是int类型的包装类,这里就涉及到Java的自动装箱与拆箱了。那什么是自动装箱与拆箱呢?

Java中的自动装箱与拆箱

从Java SE5开始就提供了自动装箱与拆箱的特性。装箱就是自动将基本数据类型转换为包装器类型;拆箱是自动将包装器类型转换为基本数据类型。如下所示:

Integer m = 100; //装箱

int y = m; //拆箱

装箱与拆箱的底层实现

我们以Integer类为例,下面先看一段代码:

​​​​​​​public class Case {
    public static void main(String[] args) {
        Integer m = 100;
        int y = m;
    }
}

这段代码反编译的字节码如下:

从反编译得到的字节码内容可以看出,在装箱的时候自动调用的是Integer的valueOf(int)方法,而在拆箱的时候自动调用的是Integer的intValue方法。其他的基本类型也类似,感兴趣的小伙伴可以去尝试一下!

接下来我们就需要查看Integer.valueOf方法的源码,我们来看一下:

从上我们能够看出,这里用到了IntegerCache,接下来我们来看一下IntegerCache类,我们发现IntegerCache是Integer的一个内部类:

我们可以从源码中发现,原来Integer类里面默认自带缓存,缓存范围默认为[-128-127]。这样我们就能解释上面例子的情况了,10在缓存范围内,所以两次返回的都是相同的对象,而128不在缓存范围内,所以每次都会新建一个Intger对象,这样就导致两个对象不等。

三、解决方法

要解决我们上面的问题,我们只需要使用Integer.intValue()方法就可以了,修改后的代码如下:

public class Demo {

    public static void main(String[] args) {
        test(10,10);
        test(128,128);
    }
    public static void test(Integer i,Integer j){
        if(i == null || j == null){
            return;
        }
        if(i.intValue() == j.intValue()){
            System.out.println("成功!");
        }else {
            System.out.println("失败!");
        }
    }
}

控制台输出:

成功!
成功!

我们可以看到,和我们预期的答案是一致的

四、总结

Integer类默认自带了缓存,可能会导致某些情况下出现一些匪夷所思的结果,所以我们在使用的时候需要注意!

好了,今天我们就到这了,大家可以思考一个问题,Java中的8中基本数据类型都有对应的包装类,那么是不是所有的包装类内部都有缓存呢?欢迎大家下方留言! 

                                                               欢迎关注小强1024实验室,和小强一起用技术改变世界

猜你喜欢

转载自blog.csdn.net/u011147339/article/details/109210953