• 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


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

    纸上得来终觉浅 绝知此事要躬行
  • 相关阅读:
    【洛谷 P4721】【模板】—分治FFT(CDQ分治+NTT)
    【Comet OJ】模拟赛测试 Day2题解
    【Comet OJ】模拟赛测试 Day2题解
    将本地文件夹push到github仓库
    2017-3-7
    彻底理解https!
    2017-3-2 智慧吉首调研工作
    java再巩固
    2017-3-1
    不错的博客哦
  • 原文地址:https://www.cnblogs.com/renyuanwei/p/14291196.html
Copyright © 2020-2023  润新知