1. Java'da nesneleri karşılaştırma
Java'da nesneler hem referansa hem de değere göre karşılaştırılabilir.
referansları karşılaştırma
İki değişken bellekte aynı nesneyi gösteriyorsa, bu değişkenlerde depolanan referanslar eşittir. Eşitlik operatörünü ( ) kullanarak bu değişkenleri karşılaştırırsanız ==
, doğru olur ve bu sonuç anlamlı olur. Burada her şey basit.
kod | Konsol çıkışı |
---|---|
|
|
değere göre karşılaştırma
Ancak iki değişkenin aynı olan iki farklı nesneyi ifade ettiği durumlarla sıklıkla karşılaşabilirsiniz. Örneğin, aynı metni içeren iki farklı dize nesnesi.
Farklı nesnelerin aynı olup olmadığını belirlemek için equals()
yöntemi kullanın. Örneğin:
kod | Konsol çıkışı |
---|---|
|
|
Yöntem equals
, sınıfla sınırlı değildir String
. Her sınıfta var.
Kendi başınıza yazdığınız sınıflar bile ve işte nedeni.
2. Object
sınıf
Java'daki tüm sınıflar, Object
sınıfı devralır. Java'nın yaratıcıları bu yaklaşımı ortaya attı.
Ve bir sınıf, sınıfı miras alırsa Object
, sınıfın tüm yöntemlerini kazanır Object
. Ve bu, mirasın önemli bir sonucudur.
Object
Başka bir deyişle, her sınıf , kodunda onlardan bahsetmese bile, sınıfın yöntemlerine sahiptir .
Bu kalıtsal yöntemler, nesne karşılaştırmasıyla ilgili yöntemleri içerir. Bunlar equals()
ve hashCode()
yöntemlerdir.
kod | Gerçekte, sahip olacağımız şey şu: |
---|---|
|
|
Yukarıdaki örnekte, Person
ad ve yaş parametreleriyle basit bir sınıf oluşturduk, ancak tek bir yöntem oluşturmadık. Ancak tüm sınıflar sınıfı devraldığından Object
, Person
sınıfın otomatik olarak iki yöntemi vardır:
Yöntem | Tanım |
---|---|
|
Geçerli nesneyi ve geçirilen nesneyi karşılaştırır |
|
Geçerli nesnenin karma kodunu döndürür |
equals
Kesinlikle her nesnenin bir yöntemi olduğu ve farklı türdeki nesnelerin birbirleriyle karşılaştırılabileceği ortaya çıktı . Böyle bir kod mükemmel bir şekilde derlenecek ve çalışacaktır.
kod | Konsol çıkışı |
---|---|
|
|
|
|
3. equals()
yöntem
equals()
Sınıftan devralınan yöntem , Object
geçerli nesneyi geçirilen nesnelerle karşılaştırmak için en basit algoritmayı uygular: yalnızca nesnelere yapılan referansları karşılaştırır.
Person
Yöntemi çağırmak yerine sadece değişkenleri karşılaştırırsanız aynı sonucu alırsınız equals()
. Örnek:
kod | Konsol çıkışı |
---|---|
|
|
Yöntem equals
çağrıldığında , değişkende saklanan referansı değişkende saklanan referansla a
karşılaştırır .a
b
Ancak, karşılaştırma sınıf için farklı çalışır String
. Neden?
Çünkü sınıfı oluşturan insanlar, String
yöntemin kendi uygulamalarını yazdılar equals()
.
equals()
Yöntemin uygulanması
Şimdi sınıftaki eşittir yönteminin kendi uygulamamızı yazalım Person
. 4 ana vakayı ele alacağız.
equals
alır.Object
Senaryo 1 : Yöntemin çağrıldığı aynı nesne equals
de yönteme iletilir equals
. Geçerli nesnenin ve iletilen nesnenin başvuruları eşitse, yöntem döndürmelidir true
. Bir nesne kendisine eşittir.
Kodda şöyle görünecek:
kod | Tanım |
---|---|
|
Referansları karşılaştırın |
Senaryo 2 : null
yönteme geçirilir equals
- karşılaştıracak hiçbir şeyimiz yok. Yöntemin çağrıldığı nesne kesinlikle null değildir, bu nedenle bu durumda equals
geri dönmemiz gerekir .false
Kodda şöyle görünecek:
kod | Tanım |
---|---|
|
Referansları karşılaştır Geçilen nesne mi null ? |
Senaryo 3 : a olmayan bir nesneye yapılan başvuru, Person
yönteme iletilir equals
. Person
Nesne, nesne olmayana eşit midir Person
? Bu, sınıfın geliştiricisinin Person
nasıl isterse öyle karar vermesi gereken bir sorudur.
Ancak genellikle nesnelerin eşit kabul edilmesi için aynı sınıftan olması gerekir. Person
Bu nedenle, equals yöntemimize sınıfın bir nesnesinden başka bir şey iletilirse, o zaman her zaman geri döneriz false
. Bir nesnenin türünü nasıl kontrol edebilirsiniz? Bu doğru — operatörü kullanarak instanceof
.
İşte yeni kodumuz şöyle görünüyor:
kod | Tanım |
---|---|
|
Referansları karşılaştır Geçilen nesne mi null ? Geçirilen nesne bir Person |
Person
4. İki nesneyi karşılaştırma
Sonumuz ne oldu? Metodun sonuna ulaştıysak, Person
olmayan bir nesne referansımız var demektir null
. Bu yüzden onu a'ya dönüştürüyoruz Person
ve her iki nesnenin ilgili dahili verilerini karşılaştırıyoruz. Ve bu bizim dördüncü senaryomuz .
kod | Tanım |
---|---|
|
Referansları karşılaştır Geçilen nesne mi null ? Geçirilen nesne bir Typecasting değilse Person |
Ve iki nesneyi nasıl karşılaştırırsınız Person
? name
İsimleri ( ) ve yaşları ( ) aynı ise eşittirler age
. Nihai kod şöyle görünecektir:
kod | Tanım |
---|---|
|
Referansları karşılaştır Geçilen nesne mi null ? Geçirilen nesne bir Typecasting değilse Person |
Ama hepsi bu kadar değil.
İlk olarak, ad alanı bir String
, bu nedenle yöntemi çağırarak ad alanını karşılaştırmanız gerekir equals
.
this.name.equals(person.name)
İkinci olarak, name
alan şu şekilde olabilir : bu durumda onu null
arayamazsınız . equals
Aşağıdakiler için ek bir kontrole ihtiyacınız var null
:
this.name != null && this.name.equals(person.name)
Bununla birlikte, ad alanı null
her iki nesnedeyse Person
, adlar yine de eşittir.
Dördüncü senaryonun kodu şöyle görünebilir:
|
Yaşlar eşit değilse, hemen return false If this.name eşittir ise null , yöntemi kullanarak karşılaştırma yapmanın bir anlamı yoktur equals . Burada ikinci name alan eşittir null veya değildir. Yöntemi kullanarak iki ad alanını karşılaştırın equals . |
5. hashCode()
yöntem
Her iki nesnenin tüm alanlarının ayrıntılı bir şekilde karşılaştırılmasını amaçlayan yönteme ek olarak equals
, kesin olmayan ancak çok hızlı bir karşılaştırma için kullanılabilecek başka bir yöntem daha vardır: hashCode()
.
Binlerce kelimeden oluşan bir listeyi alfabetik olarak sıraladığınızı ve kelime çiftlerini tekrar tekrar karşılaştırmanız gerektiğini hayal edin. Ve kelimeler uzun, birçok harften oluşuyor. Genel olarak konuşursak, böyle bir karşılaştırma çok uzun zaman alır.
Ama hızlandırılabilir. Diyelim ki farklı harflerle başlayan kelimelerimiz var - farklı oldukları hemen anlaşılıyor. Ancak aynı harflerle başlarlarsa, sonucun ne olacağını henüz söyleyemeyiz: kelimeler eşit veya farklı olabilir.
Yöntem hashCode()
, benzer bir ilkeye göre çalışır. Bir nesne üzerinde çağırırsanız, bir kelimedeki ilk harfe benzer bir sayı döndürür. Bu sayı aşağıdaki özelliklere sahiptir:
- Özdeş nesneler her zaman aynı karma koda sahiptir
- Farklı nesneler aynı karma koda sahip olabilir veya karma kodları farklı olabilir
- Nesnelerin farklı karma kodları varsa, o zaman nesneler kesinlikle farklıdır
Bunu daha da açık hale getirmek için, bu özellikleri sözcükler açısından yeniden çerçevelendirelim:
- Özdeş sözcüklerin baş harfleri her zaman aynıdır.
- Farklı kelimelerin ilk harfleri aynı olabilir veya ilk harfleri farklı olabilir.
- Kelimelerin ilk harfleri farklıysa, kelimeler kesinlikle farklıdır
Son özellik, nesnelerin karşılaştırılmasını hızlandırmak için kullanılır:
İlk olarak, iki nesnenin karma kodları hesaplanır. Bu karma kodlar farklıysa, o zaman nesneler kesinlikle farklıdır ve bunları daha fazla karşılaştırmaya gerek yoktur.
Ancak karma kodlar aynıysa, yine de eşittir yöntemini kullanarak nesneleri karşılaştırmamız gerekir.
6. Kodlu Sözleşmeler
Yukarıda açıklanan davranış, Java'daki tüm sınıflar tarafından uygulanmalıdır. Derleme sırasında, nesnelerin doğru bir şekilde karşılaştırılıp karşılaştırılmadığını kontrol etmenin bir yolu yoktur.
Java programcıları, equals() yönteminin kendi uygulamalarını yazarlarsa ve böylece standart uygulamayı (sınıfta Object
) geçersiz kılarlarsa, yöntemin kendi uygulamalarını da hashCode()
yukarıda belirtilen kuralları sağlayacak şekilde yazmaları gerektiği konusunda evrensel bir anlaşmaya sahiptir. memnun.
Bu düzenlemeye sözleşme denir .
Sınıfınızda yalnızca equals()
veya yalnızca yöntemi uygularsanız , sözleşmeyi büyük ölçüde ihlal etmiş olursunuz (sözleşmeyi bozmuş olursunuz). hashCode()
Bunu yapma.
Diğer programcılar kodunuzu kullanırsa düzgün çalışmayabilir. Dahası, yukarıdaki sözleşmelere uymaya dayalı kod kullanacaksınız.
Bir öğe ararken, tüm Java koleksiyonları önce nesnelerin hash kodlarını karşılaştırır ve ancak bundan sonra yöntemi kullanarak bir karşılaştırma gerçekleştirir equals
.
Bu, kendi sınıfınıza bir yöntem verirseniz, equals
ancak kendi yönteminizi yazmazsanız hashCode()
veya yanlış uygularsanız, koleksiyonlar nesnelerinizle doğru çalışmayabilir.
Örneğin, bir listeye bir nesne ekleyebilir ve ardından yöntemi kullanarak onu arayabilirsiniz contains()
, ancak koleksiyon nesnenizi bulamayabilir.
GO TO FULL VERSION