Object Sınıfı — Her Nesnenin Ortak Mirası
Önce şunu oku: Polimorfizm ve Dinamik Bağlama — Kararı Kim Veriyor?
30 saniyede özet
Java'daki her sınıf Object'ten türer ve ondan toString, equals ve hashCode'u miras alır. toString nesneyi tanıtır, equals iki nesnenin eşitliğine karar verir; equals'ı yazdıysan hashCode'u da yazarsın.
Bir ailenin bütün torunları büyük dededen bir şeyler taşır: bir soyadı, belki bir alışkanlık. Kimse bunu seçmez; doğuştan gelir.
Java’da bütün sınıfların ortak bir büyük dedesi vardır ve ondan birkaç alışkanlık miras alırlar.
Adım adım oku
- En tepede Object sınıfı duruyor.
- String, ArrayList ve Hesap onun torunları.
- Üçü de toString, equals ve hashCode metotlarını miras alıyor.
- Hesap toString'in kendi sürümünü yazıyor; ötekiler mirası kullanmaya devam ediyor.
-
Bayt: Hesabı log'a yazdırdım, ekranda Hesap@1b6d3586 çıktı. Bu ne?
-
Sen: Hiç toString yazmış mıydın?
-
Bayt: Hayır... Demek ki miras kalan toString'i kullanmış.
-
Bayt: Büyük dededen gelen bu üç metodu tanıyalım. Birkaçını kendimiz yazacağız.
Her sınıfın gizli atası
Bir sınıfın başına extends yazmazsan Java onu kendiliğinden ObjectJava'daki bütün sınıfların en üstteki atası. extends yazılmayan her sınıf kendiliğinden ondan türer.Her nesneye toString, equals ve hashCode gibi metotları miras bırakır. Miras hâlleri basittir: equals yalnızca aynı nesne olup olmadığına bakar.Sözlükte gör → sınıfından türetir. Bu yüzden her nesnede birkaç hazır metot vardır.
| Metot | Ne yapar | Miras hâli |
|---|---|---|
toString() | Nesneyi metin olarak tanıtır | Sınıf adı, @ ve bir sayı |
equals(Object) | İki nesne eşit mi | Yalnızca aynı nesne mi (==) |
hashCode() | Nesnenin rafını seçen sayı | Nesneye özgü bir sayı |
Miras hâlleri güvenli ama çoğu zaman işe yaramaz. İki farklı hesap nesnesi aynı IBAN’ı taşısa bile miras equals onlara “farklı” der.
Kafam karıştı, daha basit anlat
Her sınıf, yazmasan bile Object’in çocuğudur. Object ona üç hazır metot bırakır; hazır hâlleri çok basittir, bu yüzden çoğu zaman kendi sürümünü yazarsın.
`class Hesap { }` yazdın, hiç extends yok. Hesap hangi sınıftan türer?
toString: nesnenin kendini tanıtması
Hesap sınıfında toString yazılmamış. `System.out.println(new Hesap("TR01"));` ne yazdırır? Cevabı göster
Hesap@1b6d3586 gibi bir şey: sınıfın adı, @ ve nesneye özgü bir sayının onaltılık hâli. İçindeki IBAN görünmez, çünkü miras toString alanları bilmez.
println, + ile metin birleştirme ve log kütüphaneleri nesneyi yazarken toString’i çağırır. Kendi toString’ini yazarsan nesne anlamlı bir metinle kendini tanıtır.
@Overridepublic String toString() { return "Hesap[iban=" + iban + ", bakiye=" + bakiye + "]";}// System.out.println(hesap) → Hesap[iban=TR01, bakiye=100]Kafam karıştı, daha basit anlat
toString, nesnenin “ben kimim” cevabıdır. Yazmazsan Java kalıp bir cevap verir; yazarsan log’larda neye baktığını hemen anlarsın.
toString yazılmamış bir Hesap nesnesini yazdırınca ekrana `Hesap@1b6d3586` gibi bir şey çıkıyor. Bu nereden geliyor?
Program ne yazdırır?
Satır satır: equals nasıl yazılır?
İki hesap aynı IBAN’ı taşıyorsa eşit sayılsın istiyoruz. Güvenli bir equals dört adımdan oluşur.
Güvenli bir equals
@Overridepublic boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Hesap diger = (Hesap) o; return iban.equals(diger.iban);}Debug
imza Parametre Object olmalı. equals(Hesap) yazarsan miras metodun yerine geçmez, yanına yeni bir metot eklersin.
Sol/sağ ok tuşlarıyla da gezebilirsin.
Bu equals yazıldı ama `list.contains(new Hesap("TR01"))` hâlâ false dönüyor. Hatalı satır hangisi?
equals’ın sözleri ve hashCode
equals’ın bir equals sözleşmesiequals metodunun uyması gereken kurallar: kendine eşit, simetrik, geçişli, tutarlı ve null'a eşit değil.Kardeş kural: equals true diyorsa hashCode'lar da eşit olmalı. Kurallar bozulursa HashMap, HashSet ve contains gibi yapılar şaşırır.Sözlükte gör → vardır. Nesne kendine eşittir; a b’ye eşitse b de a’ya eşittir; a b’ye, b c’ye eşitse a da c’ye eşittir; sonuç değişmedikçe aynı kalır; hiçbir nesne null’a eşit değildir.
Bir de kardeş kuralı var: equals’ı yazdıysan hashCode’u da aynı alanlarla yazarsın. Yoksa eşit iki nesne HashMap’te farklı raflara düşer ve biri bulunamaz; bunun ayrıntısı HashMap dersinde.
@Overridepublic int hashCode() { return iban.hashCode();}Bir sınıf yalnızca veri taşıyorsa record yaz: toString, equals ve hashCode’u bütün alanlarla senin yerine üretir.
Kafam karıştı, daha basit anlat
equals’ı yazdıysan hashCode’u da yaz, ikisi aynı alanlara baksın. Bunu elle yazmak istemiyorsan record kullan; Java üçünü de senin yerine yazar.
Aynı IBAN, aynı hesap mı?
Tohum 726867Hesap a = new Hesap("TR01"); Hesap b = new Hesap("TR01");
Oynat ya da adımla: her adımda bir kontrol çalışır.
Şu an ne oldu?
Yalnızca equals(Object)
a ve b ayrı nesneler, ikisinin IBAN’ı da TR01.
Görevler0/3
Listede bulunan nesneyi HashSet’te kaybetaçık
İpucu
Varsayılan ayarlar yeter.
a.equals(b) true olsun ama liste b’yi bulamasınaçık
İpucu
İmzaya dikkat.
Dört kontrolün hepsi beklenen cevabı versinaçık
İpucu
Sözleşmenin iki yarısı ve kendini tanıtma.
Olay günlüğü (0)
Henüz olay yok. Oynat veya adımla.
- Varsayılanla oynat. Yalnızca equals yazılı: liste b’yi buldu, HashSet bulamadı.
- “equals(Hesap)” seç.
a.equals(b)true döndü, ama liste b’yi bulamadı: yanlış imza Object’in equals’ının yerine geçmedi. - “equals(Object) + hashCode” seç ve “toString de yazıldı”yı aç. Dört kontrol de beklenen cevabı verdi.
equals'ı IBAN'a göre yazdın ama hashCode'u yazmadın. Hangi sorun çıkar?
Bir bankada bunun en tipik yeri IBAN gibi değer nesneleridir: boşluklu ya da boşluksuz yazılmış aynı IBAN eşit sayılmalı, log’da da okunur görünmelidir.
Derinleş · Iban: eşitlik, hash ve okunur bir tanıtım 2 dosya · ~36 satır · ilk okumada atlayabilirsin
Tuzaklar
toString’e hassas veri koymak. toString log’lara, hata mesajlarına ve ekranlara gider; parola, T.C. kimlik numarası ya da tam kart numarası orada olmamalı, gerekiyorsa maskelenmeli.
Değişen alanlarla equals ve hashCode. Nesne bir HashSet’e girdikten sonra o alan değişirse nesne yanlış rafta kalır. Eşitliği değişmeyen alanlara bağla.
instanceof ile alt sınıf karışıklığı. Alt sınıf yeni bir alan ekleyip eşitliğe katarsa, a.equals(b) true iken b.equals(a) false çıkabilir. Emin değilsen getClass() karşılaştırması ya da final sınıf daha güvenlidir.
Musteri sınıfının toString'i `"Musteri[ad=" + ad + ", tckn=" + tckn + ", sifre=" + sifre + "]"` döndürüyor. En büyük sorun nedir?
Kendini sına
extends yazılmayan bir sınıfın hiç üst sınıfı yoktur.
Hangisi equals sözleşmesinin bir parçası değildir?
Aklında kalacak üç şey
- 1 Her sınıf, extends yazmasa bile Object'ten türer ve toString, equals, hashCode metotlarını ondan miras alır.
- 2 equals'ın beş sözü vardır: kendine eşit, simetrik, geçişli, tutarlı ve null'a hiç eşit değil; bu sözler bozulursa koleksiyonlar şaşırır.
- 3 equals'ı yazdıysan hashCode'u da aynı alanlarla yazarsın; toString'e ise hassas veri koymazsın.
5 kart sonraki derste seni bekliyor
Bu dersin üstüne kurulanlar
Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.