1. Membandingkan objek dalam Java
Di Java, objek boleh dibandingkan dengan rujukan dan nilai.
Membandingkan rujukan
Jika dua pembolehubah menunjuk ke objek yang sama dalam ingatan, maka rujukan yang disimpan dalam pembolehubah ini adalah sama. Jika anda membandingkan pembolehubah ini menggunakan operator kesamaan ( ==
), anda akan menjadi benar dan keputusan itu masuk akal. Semuanya mudah di sini.
Kod | Output konsol |
---|---|
|
|
Membandingkan mengikut nilai
Tetapi anda selalunya boleh menghadapi situasi di mana dua pembolehubah merujuk kepada dua objek berbeza yang serupa. Contohnya, dua objek rentetan berbeza yang mengandungi teks yang sama.
Untuk menentukan sama ada objek yang berbeza adalah sama, gunakan equals()
kaedah. Sebagai contoh:
Kod | Output konsol |
---|---|
|
|
Kaedah ini equals
tidak terhad kepada String
kelas. Setiap kelas ada.
Malah kelas yang anda tulis sendiri, dan inilah sebabnya.
2. Object
kelas
Semua kelas di Jawa mewarisi Object
kelas tersebut. Pencipta Java menghasilkan pendekatan ini.
Dan jika kelas mewarisi Object
kelas, maka ia memperoleh semua kaedah kelas Object
. Dan ini adalah akibat utama warisan.
Dalam erti kata lain, setiap kelas mempunyai kaedah kelas Object
, walaupun kod mereka tidak menyebutnya.
Kaedah yang diwarisi ini termasuk kaedah yang berkaitan dengan perbandingan objek. Ini adalah equals()
dan hashCode()
kaedah.
Kod | Pada hakikatnya, inilah yang akan kami perolehi: |
---|---|
|
|
Dalam contoh di atas, kami mencipta Person
kelas mudah dengan nama dan parameter umur, tetapi bukan satu kaedah. Tetapi kerana semua kelas mewarisi Object
kelas, Person
kelas secara automatik mempunyai dua kaedah:
Kaedah | Penerangan |
---|---|
|
Membandingkan objek semasa dan objek yang diluluskan |
|
Mengembalikan kod cincang objek semasa |
Ternyata setiap objek mempunyai equals
kaedah, dan objek dari jenis yang berbeza boleh dibandingkan antara satu sama lain. Kod sedemikian akan disusun dan berfungsi dengan sempurna.
Kod | Output konsol |
---|---|
|
|
|
|
3. equals()
kaedah
Kaedah equals()
, yang diwarisi daripada Object
kelas, melaksanakan algoritma paling mudah untuk membandingkan objek semasa dengan objek yang diluluskan: ia hanya membandingkan rujukan kepada objek.
Anda mendapat hasil yang sama jika anda hanya membandingkan Person
pembolehubah dan bukannya memanggil equals()
kaedah. Contoh:
Kod | Output konsol |
---|---|
|
|
Apabila equals
kaedah dipanggil pada a
, ia hanya membandingkan rujukan yang disimpan dalam a
pembolehubah dengan rujukan yang disimpan dalam b
pembolehubah.
Walau bagaimanapun, perbandingan berfungsi secara berbeza untuk String
kelas. kenapa?
Kerana orang yang mencipta String
kelas menulis pelaksanaan kaedah mereka sendiri equals()
.
Pelaksanaan equals()
kaedah
Sekarang mari kita tulis pelaksanaan kita sendiri kaedah sama dalam Person
kelas. Kami akan mempertimbangkan 4 kes utama.
equals
kaedah, ia sentiasa mengambil Object
objek sebagai hujah
Senario 1 : objek yang sama di mana equals
kaedah dipanggil juga dihantar kepada equals
kaedah. Jika rujukan objek semasa dan objek yang diluluskan adalah sama, kaedah mesti kembali true
. Objek adalah sama dengan dirinya sendiri.
Dalam kod ia akan kelihatan seperti ini:
Kod | Penerangan |
---|---|
|
Bandingkan rujukan |
Senario 2 : null
diserahkan kepada equals
kaedah — kita tiada apa-apa untuk dibandingkan. Objek di mana equals
kaedah dipanggil pastinya tidak batal, jadi kita perlu kembali false
dalam kes ini.
Dalam kod ia akan kelihatan seperti ini:
Kod | Penerangan |
---|---|
|
Bandingkan rujukan Adakah objek yang diluluskan null ? |
Senario 3 : rujukan kepada objek yang bukan a Person
dihantar kepada equals
kaedah. Adakah Person
objek sama dengan bukan Person
objek? Itu adalah soalan untuk pembangun kelas Person
untuk memutuskan apa yang dia mahu.
Tetapi biasanya objek mestilah daripada kelas yang sama untuk dianggap sama. Oleh itu, jika sesuatu selain daripada objek kelas Person
diserahkan kepada kaedah sama kita, maka kita akan sentiasa kembali false
. Bagaimanakah anda boleh menyemak jenis objek? Betul — dengan menggunakan instanceof
operator.
Inilah rupa kod baharu kami:
Kod | Penerangan |
---|---|
|
Bandingkan rujukan Adakah objek yang diluluskan null ? Jika objek yang dilalui bukan a Person |
4. Membanding dua Person
objek
Apa yang telah kita lalui? Jika kita telah mencapai penghujung kaedah, maka kita mempunyai Person
rujukan objek yang bukan null
. Jadi kami menukarnya kepada a Person
dan membandingkan data dalaman yang berkaitan bagi kedua-dua objek. Dan itu adalah senario keempat kami .
Kod | Penerangan |
---|---|
|
Bandingkan rujukan Adakah objek yang diluluskan null ? Jika objek yang dilalui bukan Person Typecasting |
Dan bagaimana anda membandingkan dua Person
objek? Mereka adalah sama jika mereka mempunyai nama yang sama ( name
) dan umur ( age
). Kod akhir akan kelihatan seperti ini:
Kod | Penerangan |
---|---|
|
Bandingkan rujukan Adakah objek yang diluluskan null ? Jika objek yang dilalui bukan Person Typecasting |
Tetapi bukan itu sahaja.
Pertama, medan nama ialah String
, jadi anda perlu membandingkan medan nama dengan memanggil equals
kaedah.
this.name.equals(person.name)
Kedua, name
medan itu mungkin null
: dalam kes itu, anda tidak boleh memanggilnya equals
. Anda memerlukan pemeriksaan tambahan untuk null
:
this.name != null && this.name.equals(person.name)
Yang berkata, jika medan nama berada null
dalam kedua-dua Person
objek, maka nama itu masih sama.
Kod untuk senario keempat mungkin kelihatan seperti ini:
|
Jika umur tidak sama, segera return false Jika this.name sama dengan null , tidak ada gunanya membandingkan menggunakan equals kaedah tersebut. Di sini sama ada medan kedua name adalah sama dengan null , atau tidak. Bandingkan dua medan nama menggunakan equals kaedah. |
5. hashCode()
kaedah
Sebagai tambahan kepada equals
kaedah, yang bertujuan untuk melakukan perbandingan terperinci semua medan kedua-dua objek, terdapat kaedah lain yang boleh digunakan untuk perbandingan yang tidak tepat tetapi sangat cepat: hashCode()
.
Bayangkan anda menyusun senarai beribu-ribu perkataan mengikut abjad, dan anda perlu membandingkan pasangan perkataan berulang kali. Dan perkataannya panjang, terdiri daripada banyak huruf. Secara umumnya, perbandingan sedemikian akan mengambil masa yang sangat lama.
Tetapi ia boleh dipercepatkan. Katakan kita mempunyai perkataan yang bermula dengan huruf yang berbeza — jelas sekali bahawa ia berbeza. Tetapi jika mereka bermula dengan huruf yang sama, maka kita belum boleh mengatakan apa hasilnya: perkataan itu mungkin berubah menjadi sama atau berbeza.
Kaedah ini hashCode()
berfungsi menggunakan prinsip yang sama. Jika anda memanggilnya pada objek, ia mengembalikan beberapa nombor — serupa dengan huruf pertama dalam perkataan. Nombor ini mempunyai sifat berikut:
- Objek yang sama sentiasa mempunyai kod cincang yang sama
- Objek yang berbeza boleh mempunyai kod cincang yang sama, atau kod cincang mereka mungkin berbeza
- Jika objek mempunyai kod cincang yang berbeza, maka objek itu pasti berbeza
Untuk menjadikannya lebih jelas, mari kita rangka semula sifat ini dari segi perkataan:
- Perkataan yang sama sentiasa mempunyai huruf pertama yang sama.
- Perkataan yang berbeza boleh mempunyai huruf pertama yang sama, atau huruf pertama mereka boleh berbeza
- Jika perkataan mempunyai huruf pertama yang berbeza, maka perkataan itu pasti berbeza
Sifat terakhir digunakan untuk mempercepatkan perbandingan objek:
Pertama, kod cincang kedua-dua objek dikira. Jika kod cincang ini berbeza, maka objeknya pasti berbeza, dan tidak perlu membandingkannya lagi.
Tetapi jika kod cincang adalah sama, maka kita masih perlu membandingkan objek menggunakan kaedah sama.
6. Kontrak dalam kod
Tingkah laku yang diterangkan di atas mesti dilaksanakan oleh semua kelas di Jawa. Semasa penyusunan, tiada cara untuk menyemak sama ada objek dibandingkan dengan betul.
Pengaturcara Java mempunyai perjanjian sejagat bahawa jika mereka menulis pelaksanaan mereka sendiri bagi kaedah equals() dan dengan itu mengatasi pelaksanaan standard (dalam Object
kelas), mereka juga mesti menulis pelaksanaan kaedah mereka sendiri hashCode()
sedemikian rupa sehingga peraturan yang disebutkan di atas adalah berpuas hati.
Pengaturan ini dipanggil kontrak .
Jika anda hanya melaksanakan kaedah equals()
atau hanya hashCode()
kaedah dalam kelas anda, maka anda melanggar kontrak secara besar-besaran (anda telah melanggar perjanjian). Jangan buat begini.
Jika pengaturcara lain menggunakan kod anda, ia mungkin tidak berfungsi dengan betul. Lebih-lebih lagi, anda akan menggunakan kod yang bergantung pada pematuhan kontrak di atas.
Apabila mencari elemen, semua koleksi Java mula-mula membandingkan kod cincang objek, dan hanya kemudian melakukan perbandingan menggunakan equals
kaedah tersebut.
Ini bermakna jika anda memberikan kelas anda sendiri equals
kaedah tetapi anda tidak menulis hashCode()
kaedah anda sendiri atau anda melaksanakannya dengan salah, maka koleksi mungkin tidak berfungsi dengan betul dengan objek anda.
Sebagai contoh, anda mungkin menambah objek pada senarai dan kemudian mencarinya menggunakan contains()
kaedah, tetapi koleksi mungkin tidak menemui objek anda.
GO TO FULL VERSION