Scala'daki == ve .equals arasındaki fark nedir?


144

Arasındaki fark nedir ==.equals()Scala ve içindeki ve ne zaman kullanılır?

Uygulama Java ile aynı mı?

EDIT: ilgili soru belirli vakalardan bahseder AnyVal. Daha genel durum Any.



@Ben başka bir soru, sorulan tarih dikkate alınarak yinelenen olarak işaretlenmesi gerektiğini düşünüyorum. Ayrıca, iki sorunun farklı olduğunu hissediyorum.
Jus12

Yanıtlar:


201

Normalde kullanırsanız ==, doğru şekilde equalsdavranması dışında yönlendirir null. Referans eşitliği (nadiren kullanılır) eq.


12
Java kitaplıklarını kullanırken de geçerli mi?
Jus12

20
Öyle. Örneğin, yeni java.util.ArrayList [Int] () == yeni java.util.ArrayList [Int] (), ArrayList'te eşit olarak içerik eşitliği.
Didier Dupont

5
Ayrıca Int ve Long ve == ile .equals () arasında garip bir davranış vardır. Int ve Long ile aynı sayı == için true, eşitler için false döndürür. Yani == her zaman eşittir.
Harold L

24
Daha da ilginci, Hem 3 == BigInt(3)ve BigInt(3) == 3doğrudur. Ama 3.equals(BigInt(3))yanlış, oysa BigInt(3).equals(3)doğrudur. Bu nedenle kullanmayı tercih edin ==. equals()Scala kullanmaktan kaçının . Bence ==örtük dönüşümü iyi yapıyor, ama equals()değil.
Naetmul

Öyleyse neden new java.lang.Integer(1) == new java.lang.Double(1.0)doğru ise new java.lang.Integer(1) equals new java.lang.Double(1.0)yanlıştır?
Eastsun

34

==son bir yöntemdir ve .equalsson olmayan çağrılar .

Bu, ==bir yöntemden ziyade bir işleç olan ve nesneler için referans eşitliğini kesinlikle karşılaştıran Java'dan kökten farklıdır .


29

TL; DR

  • equalsHer örneğin içeriğini karşılaştırmak için geçersiz kılma yöntemi. Bu, equalsJava'da kullanılanla aynı yöntemdir
  • Referanslar ==hakkında endişelenmeden karşılaştırmak için operatörü kullanınnull
  • eqHer iki argümanın da tam olarak aynı referans olup olmadığını kontrol etmek için yöntemi kullanın . Bunun nasıl çalıştığını anlamadığınız ve equalsbunun yerine ihtiyacınız olan şey için işe yaramayacağı sürece kullanılmaması önerilir . Ve bunu sadece AnyRefargümanlarla kullandığınızdan emin olun , sadeceAny

NOT: equalsJava'da olduğu gibi, argümanları değiştirirseniz aynı sonucu döndürmeyebilir, örneğin 1.equals(BigInt(1))tersin döneceği falseyere dönecektir true. Bunun nedeni, her uygulamanın yalnızca belirli türleri denetlemesidir. İkinci argüman ait olup olmadığını İlkel numaralar çek yok Numberne deBigInt tipte sadece diğer ilkel tiplerde

ayrıntılar

AnyRef.equals(Any)Yöntem, alt sınıflar tarafından geçersiz biridir. Java Spesifikasyonundan Scala'ya da gelen bir yöntem. Kutusuz bir örnekte kullanılırsa, bunu çağırmak için kutuludur (Scala'da gizli olsa da; int-> ile Java'da daha açıktır Integer). Varsayılan uygulama yalnızca başvuruları karşılaştırır (Java'da olduğu gibi)

Any.==(Any)Yöntem, iki nesne karşılaştırır ve (iki örneği ile statik bir yöntem çağrı sanki) ya da değişken null olmasını sağlar. Her ikisi de karşılaştırır null, sonraequals(Any) kutulu örnekte yöntemi .

AnyRef.eq(AnyRef)Yöntem karşılaştırır tek örneği belleğinde bulunduğu olduğu, referanslar. Bu yöntem için örtülü bir boks yoktur.

Örnekler

  • 1 equals 2geri falseyönlendirilirken,Integer.equals(...)
  • 1 == 2geri falseyönlendirilirken,Integer.equals(...)
  • 1 eq 2 her iki argümanın da tür olmasını gerektirdiğinden derlenmeyecektir AnyRef
  • new ArrayList() equals new ArrayList()trueiçeriği kontrol ettiği için geri dönecektir
  • new ArrayList() == new ArrayList()geri trueyönlendirilirken,equals(...)
  • new ArrayList() eq new ArrayList()her falseiki argüman da farklı örnekler olduğu için geri dönecektir
  • foo equals foodönecektir truesürece, fooolan null, daha sonra atacağımNullPointerException
  • foo == foodönecektir truebile fooolduğununull
  • foo eq fooher trueiki argüman da aynı referansa bağlandığından geri dönecektir

6

Arasında ilginç bir fark vardır ==ve equalsiçin Floatve Doubletürleri: Bunlar tedavi NaNfarklı:

scala> Double.NaN == Double.NaN
res3: Boolean = false

scala> Double.NaN equals Double.NaN
res4: Boolean = true

Düzenleme: As yorumunda işaret edildi - "Bu da Java olur" - ne olduğuna bağlıdır bu geçerli:

public static void main(final String... args) {
    final double unboxedNaN = Double.NaN;
    final Double boxedNaN = Double.valueOf(Double.NaN);

    System.out.println(unboxedNaN == unboxedNaN);
    System.out.println(boxedNaN == boxedNaN);
    System.out.println(boxedNaN.equals(boxedNaN));
}

Bu yazdırılacak

false
true
true

Yani, unboxedNanverimfalse eşitlik ile karşılaştırıldığında , çünkü IEEE kayan nokta sayıları onu bu şekilde tanımlar ve bu her programlama dilinde (kimlik kavramıyla bir şekilde karıştırılmasına rağmen) gerçekten gerçekleşmelidir.

Kutulu NaN, karşılaştırma için doğrudur. == , nesne referanslarını karşılaştırırken Java ile .

equalsDavayla ilgili bir açıklamam yok , IMHO gerçekten ==kutusuz çifte değerlerle aynı şekilde davranmalı , ama öyle değil.

Scala'ya Anyçevrildi , Scala ilkel ve nesne türlerini ilkel çifte ve kutulu Double'a gerektiği gibi birleştirdiğinden ve çevirdiğinden, biraz daha karmaşıktır . Böylece skala ==görünüşte ilkel NaNdeğerlerin bir karşılaştırmasına kadar kaybolur, ancak equalskutulu Çift değerlerde tanımlananı kullanır (devam eden çok fazla örtülü dönüşüm sihri vardır veRichDouble ).

Bir şeyin gerçekten NaNkullanılıp kullanılmadığını gerçekten öğrenmeniz gerekiyorsa isNaN:


ve bu Java'da da olur!
Iwan Satria

4

Scala == 'da önce Null değerleri kontrol edin ve sonra ilk nesnede eşittir yöntemi

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.