为什么Java中1==1为真,而128==128为假?基于享元模式的整数缓存原理分析
码到三十五 2024-10-24 11:05:03 阅读 81
❃博主首页 :
「码到三十五」
,同名公众号 :「码到三十五」,wx号 : 「liwu0213」
☠博主专栏 :
<mysql高手>
<elasticsearch高手>
<源码解读>
<java核心>
<面试攻关>
♝博主的话 :
搬的每块砖,皆为峰峦之基;公众号搜索「码到三十五」关注这个爱发技术干货的coder,一起筑基
今天我们来谈谈在Java中可能会让你感到惊讶的事情——为什么有时用==比较数字的行为并不像你期望的那样。
你可能会认为,在Java中比较两个数字时只要值相等它总是会返回true,因为两边的数字都是一样的,对吧?事实证明,在Java中并不总是那么简单。
一个小代码片段来说明这一点:
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false
Integer x = 1;
Integer y = 1;
System.out.println(x == y); // true
现在来解释一下为什么会发生这种情况,这与Java中的整数缓存有关。让我们深入探讨。
在Java中,对于基本数据类型(如int
、char
等)的比较,使用的是值比较。而对于对象(如Integer
),使用的是引用比较,即比较的是两个引用是否指向同一个对象。然而,对于Integer
类型,Java进行了一些特殊的优化,这影响了比较的结果,特别是在自动装箱和拆箱时。
分析
基本数据类型的比较:
对于基本数据类型int
,1 == 1
直接比较的是两个值,因此结果为true
。
Integer对象的比较:
Java中的Integer
类是一个对象包装类,用于包装基本数据类型int
的值。
当使用Integer
变量进行比较时(如a == b
),比较的是两个对象的引用是否相同,而不是它们包装的值。
然而,Java对Integer
类进行了优化,对于值在-128到127之间的Integer
对象,Java会缓存这些对象,即当你使用自动装箱(如Integer a = 127;
)时,如果值在这个范围内,Java会返回缓存中的对象,而不是创建一个新的对象。
基于享元模式的整数缓存魔力
Integer类在Java中使用了享元模式(Flyweight Pattern)这一设计模式。享元模式是一种对象结构型模式,它运用共享技术有效地支持大量细粒度对象的复用。在享元模式中,由于存在大量的细粒度对象,如果直接创建这些对象,可能会导致内存占用过高,性能下降。因此,享元模式通过共享对象来减少对象的数量,从而降低内存占用,提高性能。
具体说,Integer类在Java中实现了对-128到127之间整数的缓存。当创建这些范围内的Integer对象时,Integer类会返回缓存中的对象,而不是创建一个新的对象。这样做可以大大减少对象的创建数量,提高内存利用率和性能。这种缓存机制正是享元模式的一种应用。
具体情况分析
对于Integer a = 128; Integer b = 128;
:
因为128不在-128到127的缓存范围内,所以a
和b
分别指向了两个不同的Integer
对象,尽管它们的值都是128。因此,a == b
比较的是两个对象的引用,它们不同,所以结果为false
。
对于Integer x = 1; Integer y = 1;
:
因为1在-128到127的缓存范围内,所以x
和y
都指向了缓存中的同一个Integer
对象。因此,x == y
比较的是两个对象的引用,它们相同(指向同一个对象),所以结果为true
。
如何正确比较Integer
对象
想要比较两个Integer
对象所包装的值,而不是它们的引用,应该使用equals()
方法:
Integer a = 128;
Integer b = 128;
System.out.println(a.equals(b)); // true,因为比较的是值
使用equals()
方法可以确保无论Integer
对象的值是否在缓存范围内,比较的结果都是基于它们的值,而不是引用。
最后
对于基本数据类型(如int
),==
操作符比较的是值。对于对象(如Integer
),==
操作符比较的是引用。Java对Integer
对象进行了缓存优化,对于-128到127之间的值,会返回缓存中的对象。为了正确比较Integer
对象所包装的值,应使用equals()
方法。
关注公众号[码到三十五]获取更多技术干货 !
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。