1. Java-da obyektlarni taqqoslash
Java-da obyektlarni link orqali yoki qiymat orqali taqqoslash mumkin.
Link orqali taqqoslash
Agar ikkita o'zgaruvchi xotirada bir xil obyektni ko'rsatsa, ushbu o'zgaruvchilarda saqlangan linklar teng bo'ladi. Bunday o'zgaruvchilarni == tenglik operatori yordamida taqqoslasangiz, true bo'ladi, bu mantiqan to'g'ri. Bu yerda hammasi oddiy.
| Kod | Ekrandagi Chiqish |
|---|---|
|
|
Qiymat orqali taqqoslash
Biroq, ko'pincha ikkita o'zgaruvchi har xil, lekin bir xil obyektlarga ishora qilganida vaziyat yuzaga kelishi mumkin. Masalan, bir xil matnni o'zida saqlaydigan, lekin turli xil obyektlarda joylashgan ikkita satr.
Har xil obyektlarning bir xil ekanligini aniqlash uchun equals() metodidan foydalanish kerak. Misol:
| Kod | Ekrandagi Chiqish |
|---|---|
|
|
equals metodi faqat String klassida emas — bu hamma klasslarda mavjud.
Hatto siz faqatgina yozmoqchi bo'lgan klasslarda ham. Va nima uchun.
2. Object klassi
Java-dagi barcha klasslar Object klassidan meros qilib olingan deb hisoblanadi. Bu Java yaratuvchilari tomonidan o'ylab topilgan.
Agar biror klass Object klassidan meros qilib olingan bo'lsa, ushbu klassning merosxo'rida Object klassining barcha metodlari mavjud bo'ladi. Bu merosxo'rlikning asosiy ta'siri.
Boshqa so'z bilan aytganda, har bir klassda, Uni yozganingizdan qat'i nazar, Object klassiga tegishli bo'lgan barcha metodlar mavjud.
Va bunday metodlar orasida obyektlarni taqqoslash bilan bog'liq metodlar mavjud. Bu equals() va hashCode() metodlari.
| Kod | Aslida qanday bo'ladi: |
|---|---|
|
|
Yuqoridagi misolda biz name va age parametrlariga ega Person degan oddiy klass yaratdik, hech qanday metodsiz. Biroq, barcha klasslar Object klassidan meros qilib olingan deb hisoblanishi sababli, Person klassida yashirincha ikki metod paydo bo'ldi:
| Metod | Tavsif |
|---|---|
|
Joriy obyekt va uzatilgan obyektni taqqoslaydi |
|
Joriy obyektning hash-kodini qaytaradi |
Natijada equals metodi barcha obyektlarda mavjud va turli tipdagi obyektlarni bir-biriga taqqoslash mumkin, va bu hammasi juda yaxshi kompilyatsiyalanadi va ishlaydi.
| Kod | Ekrandagi Chiqish |
|---|---|
|
|
|
|
3. equals() metodi
Object klassidan meros qilib olingan equals() metodi joriy va uzatilgan obyektlarni eng oddiy algoritm bilan taqqoslaydi — u faqat ularning linklarini taqqoslaydi.
Aynan shunday ta'sir siz Person klassi o'zgaruvchilarini oddiy qilib taqqoslaganingizda bo'ladi, equals() metodini chaqirish o'rniga. Misol:
| Kod | Ekrandagi Chiqish |
|---|---|
|
|
equals metodi o'z ichidagi a va b linklarini oddiygina taqqoslaydi.
Biroq String klassi uchun taqqoslash boshqa yo'l bilan ishlaydi. Nima uchun?
Chunki String klassini ishlab chiquvchilar equals() metodining o'zlarining o'ziga xos implementatsiyasini yozishgan.
equals() metodining implementatsiyasi
Keling, biz ham Person klassida equals metodining o'ziga xos implementatsiyasini yozamiz. 4 asosiy holatni ko'rib chiqamiz.
equals metodini qayta yozganingizdan qat'i nazar, u har doim
Object tipidagi parametrni qabul qiladi.
Holat 1: equals metodiga aynan o'sha obyekt uzatilgan bo'lsa, unda equals metodini chaqirdik. Agar joriy va uzatilgan obyektlar linklari teng bo'lsa, true qaytarish kerak. Obyekt o'zi bilan o'zi mos keladi.
Kodda bu quyidagicha ko'rinadi:
| Kod | Tavsif |
|---|---|
|
Linklarni taqqoslash |
Holat 2: equals metodiga null ga ishora qiluvchi link uzatilgan — taqqoslashga hech narsa yo'q. equals metodini chaqirgan obyekt aniq null emas, shuning uchun bu holatda false qaytarish kerak.
Kodda bu quyidagicha ko'rinadi:
| Kod | Tavsif |
|---|---|
|
Linklarni taqqoslash O'tkazilgan obyekt — null? |
Holat 3: equals metodiga umuman Person klassidan bo'lmagan obyekt uzatilgan. Person klassi obyekti bo'lmagan obyekt bilan tengmi? Bu yerda Person klassi ishlab chiquvchisi qanday xohlasa, shunday qiladi.
Lekin, odatda, obyektlar bir xil tipdagi obyektlar sifatida teng hisoblanadi. Shuning uchun agar equals metodimizga Person klassidan bo'lmagan obyekt uzatilsa, biz har doim false qaytaramiz. Obyektning qanday turdaligini tekshirish uchun qanday operatorni ishlatish kerak? To'g'ri: instanceof operatori yordamida.
Bizning yangi kodimiz quyidagicha ko'rinadi:
| Kod | Tavsif |
|---|---|
|
Linklarni taqqoslash O'tkazilgan obyekt — null? Agar o'tkazilgan obyekt Person tipida bo'lmasa |
4. Ikki Person obyektini taqqoslash
Nimani oldik? Agar metoding oxirigacha yetib kelsak, demak bizda Person tipida obyekt bor va link null emas. Undan keyin uni Person tipiga o'tkazamiz va ikkala obyektning ichki qismlarini taqqoslaymiz. Bu bizning to'rtinchi holatimiz.
| Kod | Tavsif |
|---|---|
|
Linklarni taqqoslash O'tkazilgan obyekt — null? Agar o'tkazilgan obyekt Person tipida bo'lmasa Tipni o'tkazish operatsiyasi |
Ikki Person obyektini qanday taqqoslash kerak? Ular faqatgina ismlari (name) va yoshlari (age) teng bo'lsa teng hisoblanadi. Yakuniy kod quyidagicha ko'rinadi:
| Kod | Tavsif |
|---|---|
|
Linklarni taqqoslash O'tkazilgan obyekt — null? Agar o'tkazilgan obyekt Person tipida bo'lmasa Tipni o'tkazish operatsiyasi |
Lekin bu ham hammasi emas.
Birinchidan, name maydoni String tipida bo'lgani uchun, name maydonini equals metodini chaqirish orqali taqqoslash kerak.
this.name.equals(person.name)
Ikkinchidan, name maydoni null bo'lishi mumkin: shunda bu maydon uchun equals metodini chaqirish mumkin emas. Qo'shimcha null tekshiruv kerak:
this.name != null && this.name.equals(person.name)
Biroq agar name ikkala Person obyektida null bo'lsa, isimlar tengdir.
To'rtinchi holatning kodini misol uchun quyidagicha yozish mumkin:
|
Agar yoshlari teng bo'lmasa, return false darhol Agar this.name null ga teng bo'lsa, equals orqali taqqoslashning ma'nosi yo'q. Bu yerda ikkinchi name maydoni null ga teng yoki emas. equals orqali ikki name fieldsini taqqoslash. |
5. hashCode() metodi
equals metodidan tashqari, u barcha maydonlarning detalli taqqoslashini bajaradi, yana bir metod mavjud bo'lib, u aniq bo'lmagan, lekin juda tez taqqoslash uchun ishlatilishi mumkin — hashCode().
Faraz qiling, siz alfavit tartibida minglab so'zlardan iborat ro'yxatni saralamoqdasiz va siz doimo so'zlarni juft-juft taqqoslashingiz kerak. So'zlar uzun, harflar ko'p. Xullas, bu taqqoslash juda uzoq davom etadi.
Biroq uni tezlashtirish mumkin. Masalan, so'zlar turli harflardan boshlanadi: darhol ular turli ekanligi ma'lum bo'ladi. Agar ular bir xil harflardan boshlansa, keyin esa hech qanday kafolat yo'q: keyinchalik so'zlar ham teng, ham turli bo'lishi mumkin.
Metod hashCode() shu kabi tamoyilda ishlaydi. Agar obyektdan chaqirilsa, u biror raqam qaytaradi — bu so'zning birinchi harfiga o'xshaydi. Ushbu raqam quyidagi xususiyatlarga ega:
- Teng obyektlar har doim bir xil hash-kodga ega
- Turli obyektlar bir xil hash-kodga ega bo'lishi mumkin, yoki har xil
- Agar objeklar hash-kodlari turlicha bo'lsa, obyektlar aniq turli
Ko'proq tushuncha uchun ushbu xususiyatlarni so'zlarga nisbatan qayta yozamiz:
- Teng so'zlar har doim bir xil birinchi harflarga ega
- Turli so'zlar bir xil birinchi harflarga ega bo'lishi mumkin yoki har xil
- Agar so'zlarning birinchi harflari turlicha bo'lsa, so'zlar aniq turli
Oxirgi xususiyat obyektlarni tez taqqoslashda ishlatiladi:
Dastlab ikki obyektning hash-kodlari hisoblanadi. Agar bu hash-kodlar har xil bo'lsa, obyektlar aniq turli va ularni keyinchalik taqqoslash shart emas.
Agar hash-kodlar bir xil bo'lsa, obyektlarni equals yordamida taqqoslash kerak bo'ladi.
6. Kodda kontraktlar
Yuqorida tasvirlangan harakatlar Java-dagi barcha klasslar tomonidan amalga oshirilishi kerak. Obyektlarni to'g'ri taqqoslashni darajaviy insofsizlik yoki xatolarni tekshirishning hech qanday yo'li yo'q.
Barcha Java-dasturchilari kelishib olishgan, agar ular o'z equals() metodining implementatsiyasini yozishsa, standarta o'rniga (Object klassidan), ular shuningdek hashCode() metodini ham o'z implementatsiyasini yozishga majbur, shunda yuqorida aytib o'tilgan qoidalar saqlanadi.
Bunday kelishuv kontrakt deb ataladi.
Agar siz o'z klassingizga faqat bitta equals() yoki faqat hashCode() metodining implementatsiyasini qo'shsangiz, siz qo'pol ravishda kontraktni (kelishuvni) buzgan bo'lasiz. Bunday qilish mumkin emas.
Boshqa dasturchilar sizning kodingizni ishlatganida, u noto'g'ri ishlashi mumkin. Bundan tashqari, siz ham yuqorida aytilgan kontraktlarga asoslangan kodlardan foydalanasiz.
Java-dagi barcha kolleksiyalar ichidagi elementni qidirishda birinchi navbatda obyektlarning hash-kodlarini taqqoslashadi, keyin esa taqqoslash uchun equals metodini chaqiradi.
Shuning uchun agar siz o'z klasangizni yozsangiz va yangi equals metodini qo'shsangiz, lekin hashCode() metodini yozmasangiz yoki uni xatolar bilan amalga oshirsangiz, kolleksiyalar sizning obyektlaringiz bilan noto'g'ri ishlashi mumkin.
Masalan, siz ob'ektni ro'yxatga qo'shgan bo'lsangiz, so'ngra contains() metod yordamida uni qidirsangiz, kolleksiya sizning obyektingizni topmasligi mumkin.
GO TO FULL VERSION