Integer对象比较时的注意事项

01 JAVA 专栏收录该内容
107 篇文章 0 订阅

1,关于Integer对象的比较,主要是注意如下知识点(xxx表示某个整数值);

Integer a1 = xxx;与Integer a1 = Integer.valueOf(xxx);是完全相同的赋值方式的,只是前者是自动装箱,后者是手动编码装箱,以下可以说明:

对于如下code

    public static void main(String[] args) {
        Integer a1 = 127;
        Integer b1 = 127;
        // 第1处,true
        System.out.println(a1 == b1);
}

通过反编译其对应的class文件,得到的如下汇编指令中我们可以看到 Integer a1 = 127; 赋值操作实际上是通过调用Integer.valueOf(int i))方法来完成自动装箱的

  public static void main(java.lang.String[]);
    Code:
       0: bipush        127
       2: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       5: astore_1
       6: bipush        127
       8: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      11: astore_2
      12: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      15: aload_1
      16: aload_2
      17: if_acmpne     24
      20: iconst_1
      21: goto          25
      24: iconst_0
      25: invokevirtual #4                  // Method java/io/PrintStream.println:(Z)V

对于Integer.valueOf(xxx); 如果xxx>= -127且xxx<=127时,会默认取本地缓存中的数据,否则就创建一个Integer对象

首先我们看下Integer.valueOf()方法的实现源码:

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

而其中用到的静态类IntegerCache源码如下:

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

通过IntegerCache静态类可以看出,在加载该类时会首先执行static { } 静态代码块。默认进行始化一个cache数组,并分别以[-128, 127]范围内的整数作为值创建Integer对象,分别赋值到cache数组,作为本地缓存。

回到Integer.valueOf()方法:

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

我们可以看到,

1) 如果调用该方法传入的数据值在-127和IntegerCache.high(默认为127)之间,则返回对应的缓存中的包装类对象

其中获取缓存中对象时的数组下标i + (-IntegerCache.low),是因为缓存数组下标是从0起的,下标为0时对应的是-128。所以获取-128的包装类时,对应的下标就应该为-128 + (-IntegerCache.low) = 0

2) 如果调用该方法传入的数值不在[-128, 127] 范围内时,则创建一个新的Integer对象

备注:缓存区间[-128, 127] 是可以更改的,但是区间下限-128不能更改,只能变更区间上限,且上限必须大于或等于127,可以通过-XX:AutoBoxCacheMax=<size>来配置

2,示例代码:

public class Main {

    public static void main(String[] args) {

        Integer a1 = 127;
        Integer b1 = 127;
        // 第1处,true
        System.out.println(a1 == b1);

        Integer a2 = 128;
        Integer b2 = 128;
        // 第2处,false
        System.out.println(a2 == b2);

        Integer a3 = Integer.valueOf(127);
        Integer b3 = Integer.valueOf(127);
        // 第3处,true
        System.out.println(a3 == b3);

        Integer a4 = Integer.valueOf(128);
        Integer b4 = Integer.valueOf(128);
        // 第4处,false
        System.out.println(a4 == b4);

        Integer a5 = 127;
        Integer b5 = Integer.valueOf(127);
        // 第5处,true
        System.out.println(a5 == b5);

        Integer a6 = 127;
        Integer b6 = new Integer(127);
        // 第6处,false
        System.out.println(a6 == b6);

        Integer a7 = new Integer(1);
        Integer b7 = new Integer(1);
        // 第7处,false
        System.out.println(a7 == b7);
    }
}

第1、3、5处,实际上每一个引用都是获取到的缓存中的包装类对象的地址,所以输出结果为true,

第2、4、7处,每一个引用都是指向新生成的不同的Integer对象地址,所以输出结果为fase,

第6处,a6指向的是缓存中的Integer对象地址,而b6指向新生成的Integer对象地址,所以结果为false

 

 

 

展开阅读全文
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值