Java中equals比較方法使用詳解
1、equals方法的背景
在Java中,equals方法是Object類的一個(gè)方法,用于比較兩個(gè)對象是否相等。
Java中有兩種比較對象的方法:==運(yùn)算符和equals方法。
==運(yùn)算符用于比較兩個(gè)對象的引用,如果它們指向的是同一個(gè)對象,則返回true;而equals方法用于比較兩個(gè)對象的內(nèi)容是否相等,當(dāng)它們的內(nèi)容相等時(shí),則返回true。因此,equals方法可以用于比較兩個(gè)值相同的字符串、整型等基本數(shù)據(jù)類型,或需要通過內(nèi)容比較才能確定相等的自定義類對象等。
2、equals方法的使用
如何覆蓋equals方法
在Java中,一個(gè)類如果想要正確地使用equals方法,一定要對該方法進(jìn)行覆蓋。覆蓋equals方法的意思是,將equals方法從Object類中繼承來的實(shí)現(xiàn)替換為自己的實(shí)現(xiàn)。如果不覆蓋equals方法,則調(diào)用該方法時(shí)會使用繼承的Object類的實(shí)現(xiàn),這種默認(rèn)實(shí)現(xiàn)無法提供正確的比較行為,因?yàn)樗鼰o法知道哪些屬性或狀態(tài)在兩個(gè)對象中是必須相同的。
因此,覆蓋equals方法的必要性在于提供一個(gè)自定義的比較行為,使得該方法可以正確地比較自定義類對象的內(nèi)容是否相同。而覆蓋equals方法的步驟如下:
1)確定對象相等的條件;
2)覆蓋equals方法,實(shí)現(xiàn)對象相等的比較邏輯;
3)同時(shí)覆蓋hashCode方法,確保相等的對象具有相等的hashCode值。
equals方法的實(shí)現(xiàn)
在重寫equals方法時(shí)應(yīng)該遵循以下的通用標(biāo)準(zhǔn):
1)自反性:對于任何非null的引用值x,x.equals(x)應(yīng)該返回true;
2)對稱性:對于任何非null的引用值x和y,如果x.equals(y)返回true,則y.equals(x)也應(yīng)該返回true;
3)傳遞性:對于任何非null的引用值x、y和z,如果x.equals(y)返回true,y.equals(z)也返回true,那么x.equals(z)也應(yīng)該返回true;
4)一致性:對于任何非null的引用值x和y,如果用于equals比較的對象信息沒有發(fā)生變化,那么無論進(jìn)行多少次比較,都應(yīng)該返回true或false;
5)非空性:對于任何非null的引用值x,x.equals(null)應(yīng)該返回false。
下面是一個(gè)重寫equals方法的例子,假設(shè)我們有一個(gè)自定義的EqualsDemo類:
public class EqualsDemo { private String name; private int age; private double salary; //構(gòu)造函數(shù)和getter/setter方法 // 重寫equals方法 public boolean equals(Object obj) { if (obj == this) { // 如果是同一對象,返回true return true; } if (!(obj instanceof EqualsDemo)) { // 如果obj不是Employee類對象,返回false return false; } EqualsDemo equalsDemo = (EqualsDemo)obj; // 強(qiáng)制轉(zhuǎn)換為Employee類對象 return equalsDemo.name.equals(this.name) && equalsDemo.age == this.age && equalsDemo.salary == this.salary; } // 重寫hashCode方法 public int hashCode() { int result = 17; result = 31 * result + name.hashCode(); result = 31 * result + age; long temp = Double.doubleToLongBits(salary); result = 31 * result + (int)(temp ^ (temp >>> 32)); return result; } }
在這個(gè)例子中,EqualsDemo類重寫了equals方法,比較了該類的三個(gè)屬性:name,age和salary。如果兩個(gè)EqualsDemo對象的這三個(gè)屬性都相等,則這兩個(gè)EqualsDemo對象相等。同時(shí),EqualsDemo類也重寫了hashCode方法,根據(jù)該類的屬性計(jì)算了hashCode值。
3、equals方法的使用注意事項(xiàng)
在使用equals方法時(shí),需要遵循以下注意事項(xiàng):
1)永遠(yuǎn)不要使用equals方法比較對象的類型。如果沒有覆蓋equals方法,則Object.equals(Object obj)只有在obj和本身引用同一個(gè)對象時(shí)才返回true;如果覆蓋了equals方法,則equals(Object obj)所接收的參數(shù)類型必須與本身的類型相同或可以強(qiáng)制轉(zhuǎn)換成本身類型。
2)永遠(yuǎn)不要使用equals方法比較字符串常量。在Java中,字符串常量是共享的,如果用equals方法比較兩個(gè)字符串常量,可能會導(dǎo)致不正確的結(jié)果。
3)永遠(yuǎn)不要使用equals方法比較兩個(gè)浮點(diǎn)型或雙精度型的值。由于浮點(diǎn)數(shù)在計(jì)算機(jī)內(nèi)部只能表示近似值,所以可能會導(dǎo)致不正確的結(jié)果。
4、equals方法的相關(guān)問題
1. equals方法與“==”有何區(qū)別?
在Java中,==運(yùn)算符和equals方法都可以用于比較兩個(gè)對象。它們之間的區(qū)別在于:
==運(yùn)算符用于比較兩個(gè)對象的引用,如果它們指向的是同一個(gè)對象,則返回true;
equals方法用于比較兩個(gè)對象的內(nèi)容是否相等,當(dāng)它們的內(nèi)容相等時(shí),則返回true。
例如:
Integer a = new Integer(10); Integer b = new Integer(10); System.out.println(a == b); //false System.out.println(a.equals(b)); //true
在這個(gè)例子中,a和b是兩個(gè)不同的Integer對象,雖然它們的值相同,但是它們指向的是不同的對象,因此使用==運(yùn)算符比較時(shí)返回false。但是,因?yàn)樗鼈兊闹迪嗤?,使用equals方法比較時(shí)返回true。
2.equals方法與hashCode方法有何聯(lián)系?
在Java中,每個(gè)對象都有一個(gè)默認(rèn)的hashCode值,該值是一種與該對象有關(guān)的整數(shù),并且具有以下特性:
1)如果兩個(gè)對象相等,則它們的hashCode值一定相等;
2)如果兩個(gè)對象的hashCode值相等,則它們不一定相等。
因此,在覆蓋equals方法時(shí),必須同時(shí)覆蓋hashCode方法,以保證相等的對象具有相等的hashCode值。hashCode方法返回的值應(yīng)該根據(jù)equals方法比較的對象信息計(jì)算得出,具體實(shí)現(xiàn)方式可以借鑒上面的例子。
3. equal方法的效率問題
在Java中,equals方法的執(zhí)行效率可能會受到多種因素的影響,例如equals方法的實(shí)現(xiàn)邏輯、對象屬性的數(shù)量和類型等。因此,在比較大規(guī)模的對象時(shí),equals方法的效率可能會顯著降低。
為了提高equals方法的執(zhí)行效率,可以考慮以下幾種方法:
1)先比較兩個(gè)對象的hashCode值,如果它們的hashCode值不同,則這兩個(gè)對象不相等,可以直接返回false;
2)將equals方法的比較順序調(diào)整,將屬性值變化頻率低的屬性放在前面比較;
3)使用緩存,將對象的hashCode值緩存起來,避免重復(fù)計(jì)算。
補(bǔ)充知識:重寫equals方法練習(xí)
package object; /* 判斷兩個(gè)person對象的內(nèi)容是否相等 如果兩個(gè)person對象的各個(gè)屬性值都一樣,則返回true,反之返回false */ public class EqualsExercise { public static void main(String[] args) { Person person1 = new Person("jack", 10, '男'); Person person2 = new Person("jack", 10, '男'); System.out.println(person1.equals(person2)); //輸出結(jié)果是true } } class Person { private String name; private int age; private char gender; //重寫Object的equals方法 public boolean equals(Object obj) { //如果比較的兩個(gè)對象是同一個(gè)對象,則直接返回true if (this == obj){ //this就代表調(diào)用equals方法的那個(gè)對象,obj就是方法里面的實(shí)參 return true; } //類型判斷 if (obj instanceof Person){ //obj是Person,我們才比較 //進(jìn)行 向下轉(zhuǎn)型(即obj轉(zhuǎn)成Person); 因?yàn)槲倚枰玫給bj的各個(gè)屬性,如果不轉(zhuǎn)型,拿不到 Person p = (Person) obj; return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender; } //如果不是person,則直接返回false;總不能拿一個(gè)人跟一個(gè)狗比 return false; } public Person(String name, int age, char gender) { this.name = name; this.age = age; this.gender = gender; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public char getGender() { return gender; } public void setGender(char gender) { this.gender = gender; } }
Tips:
instanceof的用法:result = object instanceof class
instanceof左邊是對象,右邊是類;當(dāng)對象是右邊類或子類所創(chuàng)建對象時(shí),返回true;否則,返false。
總結(jié)
到此這篇關(guān)于Java中equals比較方法使用詳解的文章就介紹到這了,更多相關(guān)Java equals比較方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于SpringBoot項(xiàng)目實(shí)現(xiàn)Docker容器化部署的主要步驟
部署SpringBoot項(xiàng)目到Docker容器涉及選擇Java運(yùn)行時(shí)環(huán)境的基礎(chǔ)鏡像、構(gòu)建包含應(yīng)用程序的Docker鏡像、編寫Dockerfile、使用docker build命令構(gòu)建鏡像和使用docker run命令運(yùn)行Docker容器等步驟2024-10-10springboot使用yml文件配置多環(huán)境方式(dev、test、prod)
這篇文章主要介紹了springboot使用yml文件配置多環(huán)境方式(dev、test、prod),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09運(yùn)用Spring?Aop+注解實(shí)現(xiàn)日志記錄
我們都知道Spring框架的兩大特性分別是 IOC (控制反轉(zhuǎn))和 AOP (面向切面),這個(gè)是每一個(gè)Spring學(xué)習(xí)視頻里面一開始都會提到的,這里,如果我們使用Aop來記錄日志,那是再好不過了,感興趣的朋友跟隨小編一起學(xué)習(xí)下Spring?Aop注解實(shí)現(xiàn)日志記錄的過程吧2022-01-01SpringSecurity進(jìn)行認(rèn)證與授權(quán)的示例代碼
SpringSecurity是Spring家族中的一個(gè)安全管理框架,而認(rèn)證和授權(quán)也是SpringSecurity作為安全框架的核心功能,本文主要介紹了SpringSecurity進(jìn)行認(rèn)證與授權(quán)的示例代碼,感興趣的可以了解一下2024-06-06spring事務(wù)Propagation及其實(shí)現(xiàn)原理詳解
這篇文章主要介紹了spring事務(wù)Propagation及其實(shí)現(xiàn)原理詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-02-02java數(shù)據(jù)庫開發(fā)之JDBC的完整封裝兼容多種數(shù)據(jù)庫
這篇文章主要介紹了java數(shù)據(jù)庫開發(fā)之JDBC的完整封裝兼容多種數(shù)據(jù)庫,需要的朋友可以參考下2020-02-02Java使用設(shè)計(jì)模式中的代理模式構(gòu)建項(xiàng)目的實(shí)例展示
這篇文章主要介紹了Java使用設(shè)計(jì)模式中的代理模式構(gòu)建項(xiàng)目的實(shí)例展示,代理模式中的代理對象可以在客戶端和目標(biāo)對象之間起到中介的作用,需要的朋友可以參考下2016-05-05Java 詳細(xì)講解分治算法如何實(shí)現(xiàn)歸并排序
分治算法的基本思想是將一個(gè)規(guī)模為N的問題分解為K個(gè)規(guī)模較小的子問題,這些子問題相互獨(dú)立且與原問題性質(zhì)相同。求出子問題的解,就可得到原問題的解,本篇文章我們就用分治算法來實(shí)現(xiàn)歸并排序2022-04-04java中l(wèi)ong(Long)與int(Integer)之間的轉(zhuǎn)換方式
這篇文章主要介紹了java中l(wèi)ong(Long)與int(Integer)之間的轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10