Salam! Bu gün biz çox vacib və maraqlı bir mövzu haqqında danışacağıq, yəni Java-da obyektlərin bir-biri ilə bərabər () müqayisəsi . Həqiqətən, Java-da hansı hallarda A Obyekti B Obyektinə bərabər olacaq ? Bərabərlik və sətirlərin müqayisəsi - 1Bir misal yazmağa çalışaq:
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Konsol çıxışı:

false
Tamam, dayan. Niyə əslində bu iki maşın bərabər deyil? Biz onlara eyni xassələri vermişik, lakin müqayisənin nəticəsi yanlışdır. Cavab sadədir. Operator ==obyektlərin xassələrini deyil, bağlantıları müqayisə edir. İki obyektin 500 eyni xassələri olsa belə, müqayisənin nəticəsi yenə də yalan olacaq. Axı, bağlantılar iki fərqli obyektə , iki fərqli ünvana car1işarə edir . İnsanları müqayisə edən bir vəziyyəti təsəvvür edin. Dünyada yəqin ki, sizinlə eyni adı, göz rəngi, yaşı, boyu, saç rəngi və s. olan bir insan var. Yəni bir çox cəhətdən oxşarsınız, amma yenə də əkiz deyilsiniz və xüsusən də eyni insan deyilsiniz. İki obyekti müqayisə etmək üçün istifadə etdiyimiz zaman operator təxminən eyni məntiqi tətbiq edir . Bəs proqramınızda fərqli məntiqə ehtiyacınız olarsa? Məsələn, proqramınız DNT analizini simulyasiya edirsə. O, iki insanın DNT kodunu müqayisə etməli və onların əkiz olduğunu müəyyən etməlidir. car2 Bərabərlik və sətirlərin müqayisəsi - 2==
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Konsol çıxışı:

false
Nəticənin eyni olması məntiqlidir (hər şeydən sonra heç nə dəyişmədik), amma indi bundan məmnun deyilik! Həqiqətən də, real həyatda DNT analizi əkizlərlə qarşılaşdığımıza yüz faiz zəmanət verir. Amma proqramımız və operatorumuz ==bunun əksini deyir. Bu davranışı necə dəyişdirə bilərik və DNT testləri uyğun gələrsə, proqramın düzgün nəticə verəcəyinə əmin ola bilərik? Bu məqsədlə Java-da xüsusi metod yaradılmışdır - equals() .

Java-da Equals() metodu

toString()Daha əvvəl müzakirə etdiyimiz metod kimi , equals()Object bütün digər siniflərin əldə olunduğu Java-nın ən vacib sinfi olan sinifə aiddir . Bununla belə, equals() özü proqramımızın davranışını heç bir şəkildə dəyişməyəcək:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Konsol çıxışı:

false
Tamamilə eyni nəticə, bəs onda bu üsul niyə lazımdır? :/ Bu sadədir. Məsələ burasındadır ki, indi biz bu metodu sinfin özündə tətbiq etdiyimiz kimi istifadə etdik Object. Və əgər biz sinif koduna daxil olsaq Objectvə bu metodun onda necə tətbiq edildiyinə və nə etdiyinə baxsaq, görərik:
public boolean equals(Object obj) {
   return (this == obj);
}
Proqramımızın davranışının dəyişməməsinin səbəbi budur! Sinfin equals() metodunun daxilində Objecteyni istinad müqayisəsi, ==. Ancaq bu metodun hiyləsi ondan ibarətdir ki, biz onu ləğv edə bilərik. Üstündən təyin edilməsi sinifimizdə öz equals() metodunuzu yazmaq Manvə onun istədiyimiz kimi davranmasını təmin etmək deməkdir! man1.equals(man2)İndi çekin mahiyyətcə eyni şeyi etməsi bizi qane etmir man1 == man2. Bu vəziyyətdə nə edəcəyik:
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
Konsol çıxışı:

true
Tamamilə fərqli bir nəticə! Standart metod əvəzinə öz equals() metodumuzu yazmaqla düzgün davranışa nail olduq: indi iki insanın eyni DNT kodu varsa, proqram bizə deyir: “DNT analizi onların əkiz olduqlarını göstərdi” və həqiqəti qaytarır! Siniflərinizdə equals() metodunu ləğv etməklə siz asanlıqla lazımi obyekt müqayisəsi məntiqini yarada bilərsiniz. Biz obyektlərin müqayisəsinə yalnız ümumi mənada toxunduq. Hələ qarşıda bu mövzuda ayrıca böyük mühazirəmiz olacaq (əgər maraqlanırsınızsa, onu indi tez oxuya bilərsiniz).

Java-da sətir müqayisəsi - String müqayisəsi

Niyə biz simli müqayisələrə hər şeydən ayrı yanaşırıq? Əslində, proqramlaşdırmadakı xətlər tamamilə fərqli bir hekayədir. Birincisi, bəşəriyyət tərəfindən yazılmış bütün Java proqramlarını götürsəniz, onlarda olan obyektlərin təxminən 25% -i onlardan ibarətdir. Ona görə də bu mövzu çox vacibdir. İkincisi, sətirlərin müqayisəsi prosesi həqiqətən digər obyektlərdən tamamilə fərqlidir. Sadə bir misala baxaq:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Konsol çıxışı:

false
Amma niyə yalan? Sətirlər tam olaraq eynidir, sözbəsöz :/ Güman edə bilərsiniz: bunun səbəbi operatorun == istinadları müqayisə etməsidir! Axı s1onların s2yaddaşında müxtəlif ünvanlar var. Bu fikir ağlınıza gəldisə, nümunəmizi təkrarlayaq:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
İndi bizdə də iki bağlantı var, lakin nəticə əksinə dəyişdi: Konsol çıxışı:

true
Tamamilə qarışıqdır? :) Gəlin bunu anlayaq. Operator ==əslində yaddaşdakı ünvanları müqayisə edir. Bu qayda həmişə işləyir və buna şübhə etməyə ehtiyac yoxdur. Bu o deməkdir ki, əgər s1 == s2doğru qaytararsa, bu iki sətir yaddaşda eyni ünvana malikdir. Və həqiqətən də belədir! Sətirlərin saxlanması üçün xüsusi yaddaş sahəsi ilə tanış olmaq vaxtıdır - sətir hovuzu ( String pool) Bərabərlik və sətirlərin müqayisəsi - 3Sətir hovuzu proqramınızda yaratdığınız bütün sətir dəyərlərini saxlamaq üçün bir sahədir. Nə üçün yaradılmışdır? Daha əvvəl qeyd edildiyi kimi, simlər bütün obyektlərin böyük bir hissəsini tutur. İstənilən böyük proqramda çoxlu sətirlər yaradılır. Yaddaşa qənaət etmək üçün bu lazımdır String Pool- orada sizə lazım olan mətni olan bir xətt yerləşdirilir və gələcəkdə yeni yaradılmış keçidlər eyni yaddaş sahəsinə istinad edir, hər dəfə əlavə yaddaş ayırmağa ehtiyac yoxdur. Siz hər dəfə yazdığınız zaman String = “........”proqram sətir hovuzunda belə mətni olan sətir olub-olmadığını yoxlayır. Əgər varsa, yenisi yaradılmayacaq. Və yeni keçid bu sətirin saxlandığı sətir hovuzunda eyni ünvana işarə edəcək. Ona görə də proqramda yazdığımız zaman
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
keçid s2ilə tam olaraq eyni yerə işarə edir s1. Birinci komanda bizə lazım olan mətnlə sətir hovuzunda yeni bir sətir yaratdı və ikinciyə gəldikdə, sadəcə olaraq eyni yaddaş sahəsinə istinad etdi s1. Eyni mətnlə ən azı 500 daha sətir düzəldə bilərsiniz, nəticə dəyişməyəcək. Dayan. Bəs niyə bu nümunə əvvəllər bizim üçün işləmədi?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Düşünürəm ki, intuitiv olaraq, siz artıq səbəbin nə olduğunu təxmin edirsiniz :) Daha ətraflı oxumazdan əvvəl təxmin etməyə çalışın. Bu iki xəttin fərqli şəkildə yaradıldığını görə bilərsiniz. Biri operatorun köməyi ilə new, ikincisi isə onsuz. Səbəb məhz budur. Yeni operator bir obyekt yaratarkən onun üçün yaddaşda zorla yeni bir sahə ayırır . Və ilə yaradılmış sətir new- ilə bitmir String Pool: mətni 'a-dan eyni sətirlə tam eyni olsa belə, ayrıca obyektə çevrilir String Pool. Yəni aşağıdakı kodu yazsaq:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
Yaddaşda belə görünəcək: Bərabərlik və sətirlərin müqayisəsi - 4Və hər dəfə yeni obyekt yaradılanda newyaddaşda yeni sahə ayrılacaq, hətta yeni sətirlərin içindəki mətn eyni olsa belə! Deyəsən, operatoru sıraladıq ==, bəs bizim yeni dostumuz – equals() metodu haqqında nə demək olar?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Konsol çıxışı:

true
Maraqlıdır. Biz dəqiq nəyi bilirik s1s2yaddaşın müxtəlif sahələrinə işarə edirik. Lakin buna baxmayaraq, equals() metodu onların bərabər olduğunu deyir. Niyə? Yadda saxlayın, yuxarıda dedik ki, obyektləri sizə lazım olan şəkildə müqayisə etmək üçün sinifinizdə equals() metodu ləğv edilə bilər? Siniflə belə etdilər String. Onun ləğv edilmiş bərabər() metodu var. Və o, keçidləri deyil, sətirlərdəki simvolların ardıcıllığını müqayisə edir. Və əgər sətirlərdəki mətn eynidirsə, onların necə yaradıldığı və harada saxlanmasının əhəmiyyəti yoxdur: string hovuzda və ya ayrıca yaddaş sahəsində. Müqayisənin nəticəsi doğru olacaq. Yeri gəlmişkən, Java sətirləri hərflərə həssas olmayan şəkildə düzgün müqayisə etməyə imkan verir. Normal vəziyyətdə, sətirlərdən birini, məsələn, böyük hərflərlə yazsanız, müqayisənin nəticəsi yanlış olacaq:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Konsol çıxışı:

false
Bu halda, sinfin Stringbir metodu var equalsIgnoreCase(). Əgər müqayisənizdə əsas şey onların işi deyil, konkret simvolların ardıcıllığıdırsa, ondan istifadə edə bilərsiniz. Məsələn, bu, iki e-poçt ünvanını müqayisə edərkən faydalı olacaq:
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
Belə olan halda söhbətin eyni ünvandan getdiyi göz qabağındadır, ona görə də metoddan istifadə etmək equalsIgnoreCase()düzgün qərar olacaq.

String.intern() metodu

Sinfin Stringdaha bir çətin metodu var - intern(); Metod birbaşa 'om intern()ilə işləyir . Əgər sətirdə String Poolmetodu çağırırsınızsa , o:intern()
  • Simli hovuzda bu mətnlə bir sətir olub-olmadığını yoxlayır
  • Əgər varsa, hovuzda ona bir keçid qaytarır
  • Əgər belə deyilsə, o, bu mətni sətir hovuzuna yerləşdirir və ona keçid qaytarır.
Metodunu intern()new vasitəsilə yaradılmış sətir arayışına tətbiq etməklə, biz onu String Pool'a vasitəsilə sətir istinadı ilə müqayisə edə bilərik ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Konsol çıxışı:

true
Əvvəllər onları olmadan müqayisə etdikdə intern()nəticə yalan idi. İndi üsul “JavaRush – Java öyrənmək üçün ən yaxşı sayt!”intern() mətni ilə sətir olub-olmadığını yoxlayır. simli hovuzda. Təbii ki, var: biz onu yazanda yaratmışıq
String s1 = "JavaRush is the best site to learn Java!";
Yoxlanıldı ki, istinad s1və metodla qaytarılan istinad s2.intern()yaddaşda eyni sahəyə işarə edir və təbii ki, onlar edir :) Xülasə etmək, yadda saxlamaq və əsas qaydadan istifadə etmək üçün: Sətirləri müqayisə etmək üçün HƏMİŞƏ equals() funksiyasından istifadə edin. üsul! Sətirləri müqayisə edərkən, demək olar ki, həmişə onların mətnini müqayisə etməyi nəzərdə tutursunuz, bağlantıları, yaddaş sahələrini və s. equals() metodu tam sizə lazım olanı edir. Özünüz təhsil almağınız üçün bəzi linklər: