Varsayılan .equals ve .hashCode sınıflarım için nasıl çalışacak?


106

Kendi sınıfım olduğunu söyle

public class MyObj { /* ... */ }

Bazı nitelikleri ve yöntemleri vardır. Eşitleri GERÇEKLEŞTİRMEZ, hashCode UYGULAMAMAKTADIR.

Eşittir ve hashCode'u çağırdığımızda, varsayılan uygulamalar nelerdir? Object sınıfından mı? Ve bunlar ne? Varsayılan eşitler nasıl çalışacak? Varsayılan hashCode nasıl çalışacak ve ne geri dönecek? == sadece aynı nesneye referans verilip verilmediğini kontrol edecek, bu yüzden kolaydır, peki ya equals () ve hashCode () yöntemleri?

Yanıtlar:


94

Evet, varsayılan uygulama Object'tir (genel olarak konuşursak; equals ve / veya hashCode'u yeniden tanımlayan bir sınıftan miras alırsanız, bunun yerine bu uygulamayı kullanırsınız).

Belgelerden:

equals

Object sınıfı için eşittir yöntemi, nesneler üzerinde en ayırt edici olası denklik ilişkisini uygular; yani, boş olmayan tüm referans değerleri için x ve y, bu yöntem yalnızca ve ancak x ve y aynı nesneye başvurursa (x == y, true değerine sahiptir) döndürür.

hashCode

Makul derecede pratik olduğu kadar, Object sınıfı tarafından tanımlanan hashCode yöntemi, farklı nesneler için farklı tamsayılar döndürür. (Bu genellikle nesnenin dahili adresini bir tam sayıya dönüştürerek gerçekleştirilir, ancak bu uygulama tekniği JavaTM programlama dili tarafından gerekli değildir.)


50

Gönderen ObjectJVM uygulamaları birini:

public boolean equals(Object object) {
    return this == object;
}

public int hashCode() {
    return VMMemoryManager.getIdentityHashCode(this);
}

Her iki durumda da söz konusu nesnelerin bellek adreslerini karşılaştırmaktır.


7
JDK'nın hangi sürümünden? İçinde v6u23 ea:public native int hashCode();
khachik

@kha - Haklısın, sanırım ne yaptığını görmek için yerel uygulamalardan birini izledim
Brad Mace

10

Varsayılan uygulamaları vardır equals()ve hashCode()Nesne. Kendi uygulamanızı sağlamazsanız, bunlar kullanılacaktır. Çünkü equals()bu, bir ==karşılaştırma anlamına gelir : nesneler yalnızca tam olarak aynı nesne ise eşit olacaktır. İçin hashCode(), Javadoc iyi açıklaması var.

Daha fazla bilgi için Etkili Java, Bölüm 3 (pdf), madde 8'e bakın.


1

Evet, Objectsınıfınız Object'i örtük olarak genişlettiği için sınıftan. equalsbasitçe döner this == obj. hashCodeuygulama yereldir. Sadece bir tahmin - işaretçiyi nesneye döndürür.


2
Bellekte bulunan nesneye bir göstericidir, ancak nesnenin bellek adresi değildir. GC nesneyi bellekte hareket ettirebilir ve karma kod aynı kalacaktır.
Jeremy

@Jeremy Teşekkürler. stackoverflow.com/questions/2427631/… ilginç olabilir.
khachik

1

Kendi uygulamanızı sağlamazsanız, Object'ten türetilen bir uygulama kullanılacaktır. Sınıf örneklerinizi ie HashSet'e (aslında hashCode () kullanan herhangi bir koleksiyon) veya nesnenin eşitliğini kontrol etmesi gereken bir şeye (yani HashSet'in contains () yöntemi) koymayı planlamıyorsanız sorun değil. Aksi takdirde, istediğiniz şey buysa, yanlış çalışacaktır.

Kadar bu yöntemler sayesinde kendi uygulama sağlamak için oldukça kolaydır HashCodeBuilder ve EqualsBuilder gelen Apache Commons Lang .


(a) Neden Object sınıfının "eşittir" varsayılan uygulamasının HashSet ile doğru çalışmayacağını söylüyorsunuz? Bu, bu sayfadaki diğer cevaplarla çelişiyor. (b) Commons Lang bağlantıları için teşekkürler.
Basil Bourque

1
@Basil: Bunun çelişkili olduğunu düşünmüyorum. Elbette varsayılan uygulama işe yarar ... bir şekilde, ancak beklediğiniz gibi değil. Yani, equals () referans eşitliğini kullandığından, aksi takdirde aynı olan iki nesne varsayılan uygulama gözünde "farklı" olacaktır. Sonuç olarak, Setinizde tamamen aynı şeyin iki farklı örneğine sahip olabilirsiniz. Ve oldukça tipik Set kullanımı, kopyaları ortadan kaldırmak istediğiniz
zamandır

@ PawełDyda: Varsayılan davranış genellikle değiştirilebilir türler için doğrudur. Eğer Foove Barbir değişken tipte iki farklı örneklerine atıfta bulunulmaktadır ve bir yöntem (örneğin vardır SomeMutatingMethodbu) bu tür Foo.SomeMutatingMethod()etkilemez Baryapar aynı şekilde Foo, bu fark eşit nesneleri kabul etmek için yeterli olmalıdır.
supercat

0

IBM'in geliştirici çalışmaları şöyle diyor:

Bu varsayılan uygulama altında, iki referans yalnızca aynı nesneye atıfta bulunuyorlarsa eşittir. Benzer şekilde, Object tarafından sağlanan hashCode () öğesinin varsayılan uygulaması, nesnenin bellek adresini bir tamsayı değerine eşleyerek türetilir.

Ancak, belirli bir satıcının Java sürümünün tam uygulama ayrıntılarından emin olmak için muhtemelen en iyisi kaynak olarak bakmaktır (eğer varsa)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.