java中Integer自动装箱的坑 Integer比较不能用==

问题详情

在做leecode题时,使用到了HashMap<Character,Integer>,用Integer来记录字符的出现次数,然后需要将两个Integer进行比较。
一开始傻傻的就进行了 ==进行比较,大多数情况都是可以解决的,但是到后来,明明数值相等,却返回false。出问题了。

问题分析与解决

我马上意识到,Integer是对象,确实不能够用==来比较,这样比较是比较内存地址。
但是之前大多数情况可以用啊,为啥有时候不能用呢?

经过一波baidu、csdn之后。找到了原因。

	//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);
}

valueOf() 方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。
在 Java 8 中,Integer 缓存池的大小默认为 -128~127。
编译器会在自动装箱过程调用 valueOf() 方法,因此多个值相同且值在缓存池范围内的 Integer 实例使用自动装箱来创建,那么就会引用相同的对象。

对于我们来说,我们基本上都是用自动装箱来创建的,就是直接Integer = 10这样,或者将10直接传入map中,然后进行自动装箱,包装成Integer。
而Integer自动装箱有一个有趣的点:
在[-127,128]区间中,如果你之前创建过在区间中的Integer对象,那么再次创建该int值的对象时,此时不会再创建新的对象,而是将常量池已经存在的该Integer对象返回。
而超过这个区间,则每次就老老实实的来new新的Integer。

用下面的例子就可以证明:

		//demo
		Integer f1 = 10, f2 = 10, f3 = 130, f4 = 130;
        System.out.println(f1==f2);//true
        System.out.println(f3==f4);//false
        System.out.println(f3.intValue()==f4.intValue());//true

因为f1,f2在这个区间中,所以二者的符号变量引用的是一个对象。
而f3,f4不在这个区间中,所以是分别引用对象,故不相等。
而第三行的结果为true,就是显然了,这里是取出其中的值,为int类型,虽然二者对象不同,但其实,其中保存了一样的值。

思考

之所以会采用这样的方式,主要还是为了缓存,防止在易用区间类,重复创建多个同值的Integer对象,这样实际上是一种浪费。

同时,这里补充一下

	Integer a = 1;
	Integer b = 2;
	a += 1;
	System.out.println(a==b);//true

上面的结果也是true,当对Integer进行修改时,也会重新返回一个Integer对象,如果是区间范围内且常量池有,则返回常量池中的对象,否则new一个。

基本类型对应的其他缓冲池

boolean values true and false
all byte values
short values between -128 and 127
int values between -128 and 127
char in the range \u0000 to \u007F

扫描二维码关注公众号,回复: 12618665 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/112393928
今日推荐