今天我們將討論一個(gè)非常重要和有趣的話題,即比較對(duì)象與對(duì)象(比較字符串和等于)。那么在Java中,對(duì)象A究竟什么時(shí)候等于對(duì)象B呢?讓我們嘗試寫一個(gè)例子:控制臺(tái)輸出:假等待,停止。為什么這兩輛車不相等?我們?yōu)樗鼈兎峙淞讼嗤膶傩?,但比較的結(jié)果是假的。答案很簡(jiǎn)單。該運(yùn)算符比較對(duì)象引用,而不是對(duì)象屬性。兩個(gè)對(duì)象甚至可能有 500 個(gè)具有相同值的字段,但比較它們?nèi)匀粫?huì)產(chǎn)生 false。
==汽車1和汽車2指向兩個(gè)不同的對(duì)象,即指向兩個(gè)不同的地址。想象一下,你正在比較人們的情況。當(dāng)然,在世界的某個(gè)地方,有一個(gè)人和你有同樣的名字,眼睛的顏色,年齡,身高,頭發(fā)顏色等。這讓你們?cè)诤芏喾矫娑己芟嗨?,但你們?nèi)匀徊皇请p胞胎——你們顯然不是同一個(gè)人。
當(dāng)我們使用它來(lái)比較兩個(gè)對(duì)象時(shí),運(yùn)算符使用大致相同的邏輯。但是,如果您需要程序使用不同的邏輯,該怎么辦?例如,假設(shè)您的程序執(zhí)行 DNA 分析。它比較了兩個(gè)人的遺傳密碼,并確定他們是否是雙胞胎。 控制臺(tái)輸出:false 我們得到相同的邏輯結(jié)果(因?yàn)槲覀儧]有太大變化),但現(xiàn)在這個(gè)邏輯不好!畢竟,在現(xiàn)實(shí)生活中,DNA分析應(yīng)該給我們100%的保證,我們有雙胞胎站在我們面前。但是我們的程序和操作員告訴我們相反的情況。我們?nèi)绾胃淖冞@種行為,并確保程序在DNA匹配時(shí)輸出正確的結(jié)果?Java對(duì)此有一種特殊的方法:==
==等于().喜歡到字符串()方法,我們之前討論過,等于()屬于對(duì)象class — Java 中最重要的類,所有其他類派生自的類。但等于()不會(huì)自行更改程序的行為: 控制臺(tái)輸出: false 完全相同的結(jié)果,那么我們需要此方法做什么呢?:/一切都很簡(jiǎn)單。這里的問題是,我們目前正在使用此方法,因?yàn)樗窃?/p>
對(duì)象類。如果我們進(jìn)入代碼對(duì)象類并查看方法的實(shí)現(xiàn),這就是我們將看到的:這就是程序行為沒有改變的原因!完全相同的運(yùn)算符(用于比較引用)在
==等于()方法對(duì)象類。但是這種方法的訣竅在于我們可以覆蓋它。覆蓋方式編寫自己的等于()我們的方法男人類,給它我們需要的行為!目前,我們不喜歡這樣一個(gè)事實(shí):人1.等于(人2)本質(zhì)上等效于人1 == 人2.以下是我們?cè)谶@種情況下將執(zhí)行的操作: 控制臺(tái)輸出:true 現(xiàn)在我們得到了一個(gè)完全不同的結(jié)果!通過編寫我們自己的
等于()方法并使用它而不是標(biāo)準(zhǔn)方法,我們已經(jīng)產(chǎn)生了正確的行為:現(xiàn)在,如果兩個(gè)人具有相同的DNA,程序報(bào)告“DNA分析已證明他們是雙胞胎”并返回真實(shí)!通過覆蓋等于()方法在你的類中,你可以很容易地創(chuàng)建任何你需要的對(duì)象比較邏輯。事實(shí)上,我們剛剛談到了對(duì)象比較。在我們面前,關(guān)于這個(gè)主題仍然有一個(gè)很大的獨(dú)立課程(如果你有興趣,你現(xiàn)在瀏覽一下)。
在 Java 中比較字符串
為什么我們要將字符串比較與其他所有內(nèi)容分開考慮?現(xiàn)實(shí)情況是,字符串本身就是編程中的一個(gè)主題。首先,如果你把所有曾經(jīng)編寫的Java程序都拿來(lái),你會(huì)發(fā)現(xiàn)其中大約25%的對(duì)象是字符串。所以這個(gè)話題非常重要。其次,比較字符串的過程確實(shí)與其他對(duì)象非常不同??紤]一個(gè)簡(jiǎn)單的例子:控制臺(tái)輸出:false 但是為什么我們得到假呢?畢竟,字符串完全相同,逐字逐句:/您可能已經(jīng)猜到了原因:
這是因?yàn)檫\(yùn)算符比較引用==!清楚s1和s2內(nèi)存中具有不同的地址。如果你想到這一點(diǎn),那么讓我們重新制作我們的例子:現(xiàn)在我們又有兩個(gè)引用,但結(jié)果恰恰相反:控制臺(tái)輸出:真的無(wú)助地困惑?讓我們弄清楚發(fā)生了什么。操作員確實(shí)比較了內(nèi)存地址。這總是正確的,你不需要懷疑它。這意味著如果
==s1 == s2返回 true,則這兩個(gè)字符串具有相同的地址。這是真的!現(xiàn)在是時(shí)候向您介紹用于存儲(chǔ)字符串的特殊內(nèi)存區(qū)域:字符串池
字符串池是用于存儲(chǔ)您在程序中創(chuàng)建的所有字符串值的區(qū)域。為什么創(chuàng)建它?如前所述,字符串表示所有對(duì)象的巨大百分比。任何大型程序都會(huì)創(chuàng)建大量字符串。創(chuàng)建字符串池是為了節(jié)省內(nèi)存:字符串被放置在那里,然后創(chuàng)建的字符串引用相同的內(nèi)存區(qū)域 - 無(wú)需每次都分配額外的內(nèi)存。每次你寫字符串 = “.....”程序檢查字符串池中是否有相同的字符串。如果有,則不會(huì)創(chuàng)建新字符串。新的引用將指向字符串池中的相同地址(相同字符串所在的地址)。所以當(dāng)我們寫
s2指向 與 相同的位置s1.第一條語(yǔ)句在字符串池中創(chuàng)建新字符串。第二個(gè)語(yǔ)句僅引用與s1.您可以再制作500個(gè)相同的字符串,結(jié)果不會(huì)改變。等一會(huì)。如果這是真的,那么為什么這個(gè)例子以前不起作用呢? 我認(rèn)為你的直覺已經(jīng)告訴你原因=)在進(jìn)一步閱讀之前嘗試猜測(cè)。您可以看到這兩個(gè)字符串以不同的方式聲明。一個(gè)帶有新操作員,另一個(gè)沒有新操作員。原因就在這里。當(dāng)
新增功能運(yùn)算符用于創(chuàng)建對(duì)象,它強(qiáng)制為對(duì)象分配新的內(nèi)存區(qū)域。以及使用新增功能不會(huì)最終出現(xiàn)在字符串池中 — 它成為一個(gè)單獨(dú)的對(duì)象,即使它的文本與字符串池中的字符串完全匹配。也就是說(shuō),如果我們編寫以下代碼:在內(nèi)存中,它看起來(lái)像這樣:
每次使用創(chuàng)建新對(duì)象時(shí)新增功能,則分配一個(gè)新的內(nèi)存區(qū)域,即使新字符串內(nèi)的文本是相同的!看來(lái)我們已經(jīng)找到了操作員。但是我們的新認(rèn)識(shí)呢,==等于()方法? 控制臺(tái)輸出:真正有趣。我們確信
s1和s2指向內(nèi)存中的不同區(qū)域。但是等于()方法仍然告訴我們它們是相等的。為什么?請(qǐng)記住,我們之前說(shuō)過等于()方法可以被覆蓋以比較我們想要的對(duì)象?這就是他們所做的字符串類。它覆蓋等于()方法。它不是比較引用,而是比較字符串中的字符序列。如果文本相同,則它們是如何創(chuàng)建的或存儲(chǔ)在何處并不重要:無(wú)論是在字符串池中還是在單獨(dú)的內(nèi)存區(qū)域中。比較的結(jié)果將為真。順便說(shuō)一句,Java允許您執(zhí)行不區(qū)分大小寫的字符串比較。通常,如果其中一個(gè)字符串具有全部大寫字母,則比較的結(jié)果將為 false:控制臺(tái)輸出:false 對(duì)于不區(qū)分大小寫的比較,
字符串類具有等于虛無(wú)案例()方法。如果您只關(guān)心比較特定字符的順序而不是字母大小寫,則可以使用它。例如,這在比較兩個(gè)地址時(shí)可能會(huì)有所幫助:在這種情況下,我們顯然是在談?wù)撓嗤牡刂?,因此使?/p>
等于虛無(wú)案例()方法。
字符串.實(shí)習(xí)生() 方法
這字符串類還有一個(gè)棘手的方法:實(shí)習(xí)生();這實(shí)習(xí)生()方法直接與字符串池一起工作。如果您撥打?qū)嵙?xí)生()方法在一些字符串上:
它檢查字符串池中是否有匹配的字符串
如果有,它將返回對(duì)池中字符串的引用
如果不是,它將字符串添加到字符串池并返回對(duì)它的引用。
使用后實(shí)習(xí)生()字符串引用上的方法,該方法使用新增功能,我們可以使用運(yùn)算符將其與字符串池中的字符串引用進(jìn)行比較。 控制臺(tái)輸出:true 當(dāng)我們之前比較這些字符串時(shí),沒有==
實(shí)習(xí)生(),結(jié)果是錯(cuò)誤的?,F(xiàn)在實(shí)習(xí)生()方法檢查字符串“CodeGym是學(xué)習(xí)Java的最佳站點(diǎn)!”是否在字符串池中。當(dāng)然,它是:我們創(chuàng)建它與我們檢查
String s1 = "CodeGym is the best website for learning Java!";
s1和返回的引用s2.實(shí)習(xí)生()指向內(nèi)存的同一區(qū)域。當(dāng)然,他們確實(shí):)總之,記住并應(yīng)用這個(gè)重要的規(guī)則:始終使用等于()比較字符串的方法!在比較字符串時(shí),我們幾乎總是想比較它們的字符,而不是引用,內(nèi)存區(qū)域或其他任何東西。這等于()方法完全符合您的需要。