【顶得住系列】【java基础】 Integer 和 int == 比较分析

一、引言来

在java语言中,众所周知,int是基础类型,Integer是int的包装类型,属于引用类型。面试中,一般会问到两者有什么区别,答案无非就是侧重描述基础类型和引用类型的区别,这个很简单。面试难度升级就是用 ==进行比较两者,接下来就展开讨论一下这道面试题。

二、题来

            Integer a = new Integer(3); //@1
            Integer b = 3; //@2
            int c = 3; //@3
            int h = 3; //@4
            Integer d = 3;
            Integer e = 300;
            Integer f = 300;
            
            System.out.println(c == h);
            System.out.println(a == b);
            System.out.println(a == c);
            System.out.println(b == d);
            System.out.println(e == f);

想想,会打印什么内容,似乎并不容易回答出来,里面有几层小坑坑,待我细细分析。

先看看运行结果!为什么会这样呢?

【顶得住系列】【java基础】 Integer 和 int == 比较分析_第1张图片

三、分析来

我们先逐句分析一下每行代码在执行以后到底发生了什么!

Integer a = new Integer(3); //@1

Integer 是引用类型对象,所以new对象这个过程,先是在上创建了变量a,然后在上创建对象存储数值3,最后将变量a指向在堆上分配的地址。

Integer b = 3; //@2

这行代码直接将基础类型的值赋值给引用类型b,这儿就涉及到装箱的知识点。此行代码执行的时候会触发Integer.valueOf(int i)这个Integer自带方法。方法内容如下:

    public static Integer valueOf(int i) {
        //此处便是常量池,Integer的常量池范围为[-128,127]
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            //如果i变量的值在常量池范围内,则直接使用常量池的值
            return IntegerCache.cache[i + (-IntegerCache.low)];
        //如果i变量的值不在常量池的范围内,堆上新分配空间存储
        return new Integer(i);
    }

根据Integer源码分析,因为3的值在[-128,127]范围内,所以执行这段代码,会先在上创建变量b,然后将变量指向常量池中3。

int c = 3; //@3
int h = 3; //@4

上述代码,因为int是基础类型,所以执行@3行代码时,会先在栈上创建变量c,然后查找栈上有无数值3,没有存储3,然后使变量c指向它。
执行@4时候,执行流程大致与@3一致,只是因为执行到这句时,数值3在栈上已存在,所以直接使变量h指向已创建好的数值3。

所以结果分析就很明了。

System.out.println(c == h);//对于基础类型int,==都是数值比较,肯定是true

System.out.println(a == b);//因为两个变量都是引用类型,所以==比较引用的对象。 变量a引用的对象存储在堆上,变量b引用的对象在常量池,所以为false。

System.out.println(a == c);//Integer类型跟int类型比较,都按照基础类型的比较(拆箱)。因为数值相等,所以为true。

System.out.println(b == d);//因为数值的范围都在[-128,127],所以两个变量指向的对象都是常量池。所以为true。

System.out.println(e == f);//因为范围都超出[-128,127],所以两个变量指向的对象都是在堆各自新创建的堆对象。所以为false。

四、总结来

  1. 对于基础类型int,==都是数值比较。
  2. Integer和int的变量进行比较,==都按照数值比较。
  3. 直接为Integer赋基础类型数值,要考虑到数值的范围,是不是在常量池[-128,127]范围内。

言而总之,对于==,基础类型,比较值;引用类型比较引用的对象。

五、拓展来

上文我们了解Integer常量池(缓存)机制的知识点,由此发散思维,是否其它的基础类型的包装类有类似的机制。
答案是肯定的,我们常用的ShortLongByteCharacter都有类似的机制,碍于篇幅,具体细节不一一细讲,留个同志们去研究研究。
除开基础类型的包装类,还有一个String类型很特殊,后文再细讲它的内存分配以及变量比较。

你可能感兴趣的