深入理解java中的==和equals
在java开发过程中,==和equals经常被用到来对比两个‘对象’是否相等;为了提高对java基础的理解,从而更好的完成开发,特意整理了该知识点。
==和equals基本区别
a == b
1.对于基本数据类型,比较的是a和b的值;
2.对于引用类型,比较的是a和b的引用是否指向同一对象;
a.equals(b)
说明:equals方法是由Object类提供的,子类可以重写该方法。
1.调用方所属的类没重写equals方法,按Object原生equals比较
(源码中返回的结果等价a == b)
2.调用方所属的类重写了equals方法,按重写equals方法中的具体规则比较。
例1:java.lang.String中equals实现
(先通过==判断是否是指向同一地址,若不是则按字符依次对比是否完全相等)
例2:java.util.Date中equals实现
(gitTime返回一个long的值,比较这个值是否相等)
在真实场景中容易混淆的情况
上面已经把概念基本说清了,但是实际情况往往和我们判断的差异,比如下面例子:
例1:
为什么上面为true下面为false呢?
true:首先把a1等式按=分成两个部分看,编译时左边创建了一个Integer类型的a1引用,右边是一个常量(这里没有在堆中创建对象)会把10放入常量池,然后把a1指向10;定义a2时同理,只是会去判断常量池是否存在当前值(10),然后把a2指向10,所以引用相同。
false:128超出了Integer中维护的数组范围(-128 - 127),从而分别new Integer(128)创建对象,所以引用不同,部分源码如下:
例2:
s1 == s3为false:是因为string做加法时(存在引用)会通过StringBuilder来实现,然后用toString转为String类型;而StringBuilder的toString源码为:
new了一个新对象,所以s1和s3引用不同。
s0 == s1为true:是因为"a"、“b”、“c"均为常量,在编译时“+”会把多个连接的常量编译成一个常量后再存储和赋值引用,所以常量池这时只存了“abc"并把s0指向它;而s1=“abc”,会先去常量池查找是否当前存在”abc“存在则直接将s1指向常量池中的“abc”,所以s0和s1的引用相同。