Integer判等的陷阱:你知道Integer内部高速缓冲区IntegerCache吗?
https://blog.csdn.net/magician_Code/article/details/51469101
我们先来看看下面代码的运行情况:
public static void main(String[] args) { // TODO Auto-generated method stub Integer integer1; Integer integer2; integer1 = new Integer(10); integer2 = new Integer(10); //第一次比较 System.out.println("第一次比较:"+(integer1==integer2)); //第二次比较 System.out.println("第二次比较:"+(integer1==10)); integer1 = 127; integer2 = 127; //第三次比较 System.out.println("第三次比较:"+(integer1==integer2)); integer1 = 128; integer2 = 128; //第四次比较 System.out.println("第四次比较:"+(integer1==integer2)); }
运行程序,结果如下:
你看出了运行结果了吗?
第一次和第二次比较就无可厚非了,第一次是直接把两个不同的对象比较,当然是false;第二次比较时,是把Integer对象和int型10进行比较,根据自动装箱、拆箱机制,这时候的比较就等价于10==10,所以是true。那么后面两个为什么会出现两种不同的结果呢?
首先我们先来看看Integer的两种定义方式:
Integer integer1 = new Integer(10); Integer integer2 = 10;
第一种是我们常见的创建一个对象的方法,那么第二个方法呢?根据Java的自动装箱、拆箱机制,这时在Integer内部实际上是做了如下操作:
Integer integer2 = Integer.valueOf(10);
这时我们查看Integer源码中关于valueOf方法的定义:
public static Integer valueOf(int paramInt) { if ((paramInt >= -128) && (paramInt <= IntegerCache.high)) { return IntegerCache.cache[(paramInt + 128)]; } return new Integer(paramInt); }
这里我们会留意到”IntegerCache”这个类,跟踪一下代码,发现这是Integer的一个私有内部类,声明如下:
private static class IntegerCache { static final int low = -128; static final int high; static final Integer[] cache; private IntegerCache() {} static { int i = 127; String str = VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (str != null) { try { int j = Integer.parseInt(str); j = Math.max(j, 127); i = Math.min(j, 2147483518); } catch (NumberFormatException localNumberFormatException) {} } high = i; cache = new Integer[high - -128 + 1]; int k = -128; for (int m = 0; m < cache.length; m++) { cache[m] = new Integer(k++); } assert (high >= 127); } } }
这段代码并不难读,这里类缓存了从-128到127之间的所有整型对象,意思是当使用自动装箱的方式定义一个值在-128到127的Integer对象时,我们得到的是从缓存区(IntegerCache)中返回的实例。
所以,当我们在进行上面的第三次比较时,此时的integer1和integer2是同一个对象,那么比较的结果当然是true啦。第四次是因为我们指定的值为128,>127,所以Integer内部会创建新的对象返回,所以当然不可能相等。
最后啰嗦一下,如果要进行两个Integer对象基于数值的比较时,因为Integer实现了Compaeable接口,所以直接使用compaerTo方法进行比较会比较妥当。判等的话还可以使用equals方法,于是我们把最开始的代码改成如下:
public static void main(String[] args) { // TODO Auto-generated method stub Integer integer1; Integer integer2; integer1 = new Integer(10); integer2 = new Integer(10); //第一次比较 //System.out.println("第一次比较:"+(integer1==integer2)); if(integer1.equals(integer2)) System.out.println("第一次比较:"+true); else System.out.println("第一次比较:"+false); //第二次比较 System.out.println("第二次比较:"+(integer1==10)); integer1 = 127; integer2 = 127; //第三次比较 //System.out.println("第三次比较:"+(integer1==integer2)); if(integer1.equals(integer2)) System.out.println("第三次比较:"+true); else System.out.println("第三次比较:"+false); integer1 = 128; integer2 = 128; //第四次比较 //System.out.println("第四次比较:"+(integer1==integer2)); if(integer1.equals(integer2)) System.out.println("第四次比较:"+true); else System.out.println("第四次比较:"+false); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
2015-03-06 SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常见问题总结
2015-03-06 开涛spring3(9.4) - Spring的事务 之 9.4 声明式事务