int和Integer(== 和 equals的区别)

本篇文章先从一道题目开始

题目内容

    int a = 100;
    Integer b = 100;
    System.out.println(a == b); // true

    Integer a1 = 101;
    Integer b1 = 101;
    System.out.println(a1 == b1); // true

    Integer a2 = 200;
    Integer b2 = 200;
    System.out.println(a2 == b2); // false

以上的结果是否和你预期的一一致呢?如果都能正确的回答,说明对java的自动拆装箱和整数的缓存池有了一定的了解。

自动拆装箱,说的通俗易懂点就是基本类型和其包装类之间的相互转换

类型 类型转换 实现方法
装箱 int 转 Integer Integer x = Integer.valueOf(int value)
拆箱 Integer 转 int int y = x.intValue()

关于int 和 Integer之间的比较,Integer和Integer之间的比较,先看一下比较规则

比较规则

类型比较 比较规则
int 和 int == 比较的是值、无法使用equals比较
int 和 Integer 基本类型和包装类型, 会进行自动拆箱转为基础类型进行比较
Integer 和 Integer ==比较的是引用地址、equals比较的是值

在Integer 和 Integer 比较时,使用==比较的是引用地址,那么久涉及常量池(IntegerCache)的问题,分以下两种情况

1、 是否使用常量池

 - new Integer()构造方法, 不使用缓存池
 
 - Integer.valueOf()方法, 使用缓存池

2、大小是否在IntegerCache范围内

 - 在【-128 ~127】范围内,使用缓存池
 
 - 在【-128 ~127】范围外,不使用缓存池

看一下Integer的源码可知,IntegerCache是Integer的静态内部类
当使用valueOf()创建一个Integer时,
在[IntegerCache.low,IntegerCache.hign]闭区间范围内的,使用缓存池
否则使用new Integer(i)创建一个新的对象

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

IntegerCache.low=-128; IntegerCache.high =127

那么这个缓存池的范围可以修改吗?是可以的!

不过只能设置上限,下限是固定的-128

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() {}
    }

代码大致的内容:

读取java.lang.Integer.IntegerCache.high变量的值,如果不为空,和127比较大小Math.max(i, 127),将上限设置为两个中的最大值

然后初始化一个Integer数组,[-128, -127, -126, -125, -124,....... 124, 125, 126, 127]

其中new Integer(j++) 是先赋值,再加一

基于以上的结论和认识,尝试做一下下面的比较

示例一
    Integer a3 = new Integer(121);
    Integer b3 = new Integer(121);
    System.out.println(a3 == b3); // false
    System.out.println(a3.equals(b3)); // true

    Integer a4 = new Integer(300);
    Integer b4 = new Integer(300);
    System.out.println(a4 == b4); // false
    System.out.println(a4.equals(b4)); // true
示例一解读:

首先new Integer()构造方法, 不使用缓存池,所以无需考虑范围

==比较的是引用地址,创建了两个对象,所以是false

equals比较的是值,所以是true

很多人好奇为什么equale比较的是值,这个可以看一下Integer的源码
在这里插入图片描述


示例二
    Integer a5 = Integer.valueOf(122);
    Integer b5 = Integer.valueOf(122);
    System.out.println(a5 == b5); // true
    System.out.println(a5.equals(b5)); // true

    Integer a6 = Integer.valueOf(500);
    Integer b6 = Integer.valueOf(500);
    System.out.println(a6 == b6); // false
    System.out.println(a6.equals(b6)); // true
示例二解读:

Integer.valueOf()方法, 使用缓存池,使用缓存池,就需要看大小是否在IntegerCache范围内,122在缓存池范围内,500不再缓存池范围内

==比较的是引用地址,使用缓存池创建的a5和b5,实际上是同一个对象,所以是true,a6和b6的大小不再范围内,不适用缓存池,所以创建了两个对象,所以是fasle

equals比较的是值,所以是true


示例三
    Integer a7 = Integer.valueOf(133);
    Integer b7 = new Integer(133);
    System.out.println(a7 == b7); // false
    System.out.println(a7.equals(b7)); // true
示例三解读:

Integer.valueOf() 方法使用缓存池,且133在【-128 ~127】范围内,a7变量指向常量池中的133
new Integer() 构造方法不使用缓存池,b7指向堆内存中的133对象,两个对象不是同一个,所以a7 == b为false

equals比较的是值,所以是true


如果对以上的还有疑惑,重新看上面的比较规则;

posted @ 2021-01-18 09:20  上尤流苏  阅读(485)  评论(0编辑  收藏  举报