Java Int 和 Integer 值的比较问题,都答对的绝对是高手

通过本篇,你会了解到Int和Integer的比较,了解Integer的缓存机制。

至于 == 与 equals() 源码部分,可以参考我下面的文章:

浅谈 Java 字符串比较中 == 和 equals() 的区别(带源码分析)_无知君的技术分享平台-CSDN博客("^_^ " 看总结请直接拉到最下面 " ^_^ ")通常,判断两个变量是否相等有两种方式:"==" 和 equals() 方法分析:要想明白二者的不同,我们先要明确一个概念:Object 类是所有 Java 类的父类,所有的 Java 类都要继承 Object 类,通常不显式声明继承的类,都默认继承自 Object 类。equals() 是属于Object 类的方法,n...https://blog.csdn.net/weixin_44259720/article/details/88236466


1. 题目

    @Test
    void integer_test() {
        Integer a1 = new Integer(128);
        Integer a2 = new Integer(128);
        int b1 = 128;
        int b2 = 128;
        Integer c1 = 128;
        Integer c2 = 128;
        Integer d1 = 127;
        Integer d2 = 127;

        System.out.println("1.1 = " + (a1 == a2));          // false
        System.out.println("1.2 = " + (b1 == b2));          // true
        System.out.println("1.3 = " + (c1 == c2));          // false
        System.out.println("1.4 = " + (d1 == d2));          // true

        System.out.println("2.1 = " + (a1 == b1));          // true
        System.out.println("2.2 = " + (a1 == c1));          // false
        System.out.println("2.3 = " + (b1 == c1));          // true
    }

2. 解释

  1. Integer 是 int 的包装类,Integer 的默认值是 null,int 的默认值是 0;
  2. 在 new 一个 Integer 时,会重新生成一个指针指向该对象,所以:a1 != a2;
  3. Integer 是包装类,属于对象, Integer c1 = 128 <=> Integer c1 = new Integer(128);所以:a1 != c1,c1 != c2;
  4. Java 中 Integer 类型对于(-128-127)之间的数会写入Cache缓存,再次被定义时就会直接从缓存中取,所以用等号比较是一致的。比如:Integer d1 = 127 时会将127进行缓存,下次再定义 Integer d2 = 127 时,d2会直接从缓存中取,但是 c1 和 c2 的 128 不会被缓存,所以:c1 != c2,d1 == d2;
  5. Java 在编译的时候,Integer c1 = 128;会被翻译成:Integer c1 = Integer.valueOf(128);
  6. int 与 Integer 比较的时候发生自动拆箱,将 Integer 自动变为 int,不管值为多少始终是相等的,所以:a1 == b1,b1 == c1;

2.1 Integer的缓存问题

一个字节 8 位,即可表示 2^8 = 256,有符号数那就是 -128 128 了,还要考虑去除一个符号位,实际表示的范围是 -128 127,也就是说:Java 中 Integer 类型在 Cache 中会默认缓存一个字节以内的值。

上面讲到了:Integer c1 = Integer.valueOf(128);看一下 valueOf() 方法内部是怎么缓存的?源码如下:

public final class Integer extends Number implements Comparable<Integer> {
    // ...
    /**
     * Returns an {@code Integer} instance representing the specified
     * {@code int} value.  If a new {@code Integer} instance is not
     * required, this method should generally be used in preference to
     * the constructor {@link #Integer(int)}, as this method is likely
     * to yield significantly better space and time performance by
     * caching frequently requested values.
     *
     * This method will always cache values in the range -128 to 127,
     * inclusive, and may cache other values outside of this range.
     *
     * @param  i an {@code int} value.
     * @return an {@code Integer} instance representing {@code i}.
     * @since  1.5
     */
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }
    // ...
}

根据源码注释可知:

Integer.value() 会返回一个指定的 int 值的 Integer 实例。

若不需要一个新的 Integer 实例,会优先采用该方法实例化,而不是 new Integer(int i)。因为相比于使用 new Integer(int i) 的方法实例化对象,valueOf(int i) 会缓存经常请求的值 (多次请求会从缓存中获得),从而获得更好的空间和时间性能。

通过阅读源码,发现 Integer 类中存在一个静态内部类 IntegerCache,源码如下:

    /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
    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() {}
    }

根据源码上方的注释可知:

该类默认缓存值在 [-128, 127] 内的 Integer 对象,且采用一个 final 修饰的数组 cache 作为存储容器,首次使用时会初始化该缓存。

此外,缓存的上限是可以修改的,通过修改选项:-XX:AutoBoxCacheMax= 来设置缓存上限值。


3. Integer比较的方法

Integer 是 int 的包装类,相同类型的包装类对象之间的值比较,最好使用 equals。

        System.out.println("3.1 = " + (c1.equals(c2)));    // true

equals 底层原理其实就是:intValue();


おすすめ

転載: blog.csdn.net/weixin_44259720/article/details/123272084