Java'daki dizeleri nasıl karşılaştırırım?


724

==Şu ana kadar tüm dizelerimi karşılaştırmak için programımdaki operatörü kullanıyorum . Ancak, bir hataya rastladım, bunlardan birini değiştirdim .equals()ve hata düzeltildi.

==kötü? Ne zaman kullanılmalı ve kullanılmamalıdır? Fark ne?


12
Ayrıca, .equals () yöntemini geçersiz kılarsanız, .hashcode () yöntemini geçersiz kıldığınızdan emin olun, aksi takdirde b / w eşittir ve hashcode ile eşdeğerlik ilişkisini ihlal edersiniz. Daha fazla bilgi için java doc.
Nageswaran

Neden ==nesnelerdeki gibi çalıştığına ilişkin açıklamamın bağlantısını bırakarak Nesneler: stackoverflow.com/a/19966154/2284641
Johannes H.

==java, yaygın olarak kullanılan dizelerin bellek referanslarını yeniden kullanmaya çalıştığı bir String havuzuna sahip olduğu için bir süre çalışacaktır. Ancak ==nesnelerin değerlerle eşit olduğunu karşılaştırır ... .equals()kullanmak istediğiniz doğru kullanım da öyle.
James Oravec

İnce hataları izlemekten ve Java String interning işleminin inceliklerini incelemekten hoşlanmadıkça, String'lerin aynı olup olmadığını test etmek için asla == kullanmayın. "12"=="1"+2is false (muhtemelen)
Flight Odyssey

Yanıtlar:


5568

== referans eşitliği için testler (aynı nesne olup olmadıkları).

.equals() değer eşitliği testleri (mantıksal olarak "eşit" olup olmadıkları).

Objects.equals () denetler nullçağırmadan önce .equals()bunu yapmak zorunda kalmamak (JDK7 itibariyle mevcut, da mevcuttur Guava ).

Sonuç olarak, iki dizenin aynı değere sahip olup olmadığını test etmek istiyorsanız muhtemelen kullanmak isteyeceksiniz Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Neredeyse her zaman kullanmak istersiniz Objects.equals(). In nadir durumun biliyorum birlikte olduğun bir alışverişte enterne dizeleri, sen yapabilirsiniz kullanın ==.

Gönderen JLS 3.10.5. Dize Değişmezleri :

Dahası, bir dize hazır bilgisi her zaman aynı sınıf örneğini ifade eder String. Bunun nedeni, dize değişmezlerinin - veya daha genel olarak, sabit ifadelerin ( §15.28 ) değerleri olan dizelerin , yöntemi kullanarak benzersiz örnekleri paylaşmak için "interned" olmasıdır String.intern.

Benzer örnekler JLS 3.10.5-1'de de bulunabilir .

Dikkate Alınması Gereken Diğer Yöntemler

Büyük / küçük harf kullanımını göz ardı eden String.equalsIgnoreCase () değer eşitliği.

String.contentEquals () yöntemi , içeriği Stringile CharSequence(Java 1.5'ten beri kullanılabilir) karşılaştırır. Eşitlik karşılaştırması yapmadan önce StringBuffer, vb. Bir String'e dönüştürmek zorunda kalmaz, ancak null kontrol size bırakır.


3
== referans eşitliğini kontrol ederse n == 5 neden anlamlıdır? 5 bir değişken değil
Hrit Roy

2
@HritRoy Çünkü bir değişkenin değerini== kontrol eder . Bir nesneniz olduğunda, nesneye başvuran değişkenin nesnenin değeri olarak başvurusu olur . Böylece, iki değişkeni karşılaştırırken referansları karşılaştırırsınız . İlkel bir veri türünü karşılaştırırken , yine de aynı durum söz konusudur. Bir tür değişkeni değer olarak tamsayıya sahiptir. Böylece iki s değerini kullanarak karşılaştırırsınız . Eğer bir değişkenin veya sihirli bir sayının değeri önemli değilse. Buna ek olarak: Bir referans başka bir şey bellek belirtmektedir bir sayıdır. ==intintint==int
akuzminykh

719

==nesne referanslarını .equals()test eder, dize değerlerini test eder.

Bazen ==değerleri karşılaştırır gibi görünür , çünkü Java aynı satır içi dizelerin aslında aynı nesne olduğundan emin olmak için bazı sahne arkası işleri yapar.

Örneğin:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

Ama null'lara dikkat edin!

==nulldizeleri iyi işler , ancak .equals()boş bir dizeden çağırmak istisnaya neden olur:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Yani fooString1bunun boş olabileceğini biliyorsanız , okuyucuya şunu yazarak söyleyin:

System.out.print(fooString1 != null && fooString1.equals("bar"));

Aşağıdakiler daha kısadır, ancak null olup olmadığını kontrol ettiği daha az açıktır:

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required

86
Bazen "==" değerleri karşılaştırıyor gibi görünüyor, - == her zaman değerleri karşılaştırın! (Sadece belirli değerler referanstır!)
aioobe

6
Ne yazık ki, isNullOrEmpty () için statik bir yöntem ve C # veya Python'dan daha Java clunkier yapan işleçlerin özel aşırı yüklenmesi yoktur. Java'nın uzantı yöntemleri olmadığı için java.lang.String'i genişletmek için kendi yardımcı programınızı yazamazsınız. Sağ? Dize, alt sınıflandırma düşüncesi, bu statik yardımcı yöntem ekleyerek ve daha sonra her zaman bunun yerine MyString kullanarak? Sıfır değerli karşılaştırmalar yapmak için iki parametreli statik bir yöntemin de bu alt sınıfta olması iyi olur.
Jon Coombs

7
Groovy bunu güvenli navigasyon operatörü ( groovy.codehaus.org/… ) ile biraz kolaylaştırıyor ?.. Bu nullString1?.equals(nullString2);tamamen boş bir ifadeye dönüşecektir. Bununla birlikte, eğer varsa validString?.equals(nullString);- bu hala bir istisna atar.
Charles Wood

5

5
@JonCoombs Java, alt sınıflamayı ve kendi yöntemini oluşturmayı destekler. Bununla birlikte, bazı sınıflar belirli nedenlerle final olarak işaretlenir, String bunlardan biridir, bu yüzden genişletemeyiz. İki dize argüman olarak alan ve mantığımızı oraya uygulayan başka bir sınıf oluşturabilir ve burada sınıf yaratabiliriz. Ayrıca null bahar ve apache gibi diğer kütüphaneleri kontrol etmek için iyi yöntemler koleksiyonları, biri bunu kullanabilirsiniz.
Panther

443

== Nesne başvurularını karşılaştırır.

.equals() Dize değerlerini karşılaştırır.

Bazen ==, aşağıdaki durumlarda olduğu gibi Dize değerlerini karşılaştırma yanılsamaları verir:

String a="Test";
String b="Test";
if(a==b) ===> true

Bunun nedeni, herhangi bir String değişmezi oluşturduğunuzda, JVM'nin önce String havuzunda bu değişmezi arar ve bir eşleşme bulursa, aynı başvuru yeni Dizeye verilecektir. Bu nedenle şunu elde ederiz:

(a == b) ===> doğru

                       String Pool
     b -----------------> "test" <-----------------a

Ancak, ==aşağıdaki durumda başarısız olur:

String a="test";
String b=new String("test");
if (a==b) ===> false

Bu durumda new String("test"), öbek üzerinde yeni String oluşturulacak ve bu referansa verilecektir b, bu nedenle bString havuzunda değil, öbek üzerinde bir referans verilecektir.

Şimdi aise dize havuzunda dize işaret ediyor byığın üzerinde bir dize işaret ediyor. Bu nedenle:

if (a == b) ===> yanlış.

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Her .equals()zaman Dize değerini karşılaştırır, böylece her iki durumda da doğrudur:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Yani kullanmak .equals()her zaman daha iyidir.


3
.equals () iki örneği karşılaştırır, ancak bunları karşılaştırmak için eşittir. Bu, toString'in çıktısını karşılaştırıyor olabilir veya olmayabilir.
Jacob

3
@Jacob Object class .equals()yöntemi, .equals()içeriği (chars) karşılaştırmak için String sınıfı yöntemlerinin geçersiz kılındığı örnekleri (başvuru / Adres) karşılaştırır
Satyadev

1
Dize havuzu, kesinlikle aynı olmadığı için Java yığın farklılıklarına karşı iyi işaret ediyor . Dize havuzunda Java değişmez Stringolduğu Stringiçin bilinen bellek ayak izi kaydetmek için nesneleri "önbellek" dener (Umarım, burada doğru söylüyorum). Ayrıca stackoverflow.com/questions/3052442/…
Roland

1
Aradığım cevap buydu.
Weezy

Ne harika bir cevap!
alwbtc


179

Java dizeleri değiştirilemez. Bu, dizeyi değiştirmeye / değiştirmeye çalıştığınızda yeni bir örnek alacağınız anlamına gelir. Orijinal dizeyi değiştiremezsiniz. Bu, bu dize örneklerinin önbelleğe alınabilmesi için yapılmıştır. Tipik bir program çok sayıda dize başvurusu içerir ve bu örneklerin önbelleğe alınması bellek kapladığı alanı azaltabilir ve programın performansını artırabilir.

Dize karşılaştırması için == operatörünü kullanırken, dizenin içeriğini karşılaştırmazsınız, ancak aslında bellek adresini karşılaştırırsınız. İkisi de eşitse, aksi takdirde doğru ve yanlış döndürür. Oysa dizedeki eşitler dize içeriğini karşılaştırır.

Yani soru, tüm dizeler sistemde önbelleğe alınmışsa, come nasıl ==false döndürür, equals true olursa ? Bu mümkün. Sizin gibi String str = new String("Testing")yeni bir dize yaparsanız, önbellek zaten aynı içeriğe sahip bir dize içeriyor olsa bile önbellekte yeni bir dize oluşturur. Kısacası "MyString" == new String("MyString")her zaman yanlış döndürür.

Java ayrıca bir dizede önbelleğin bir parçası yapmak için kullanılabilen intern () işlevinden de bahseder ve böylece "MyString" == new String("MyString").intern()true değerini döndürür.

Not: == işleci, iki bellek adresini karşılaştırdığınızdan çok daha hızlıdır, ancak kodun kodda yeni String örnekleri oluşturmadığından emin olmanız gerekir. Aksi takdirde hatalarla karşılaşırsınız.


147
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

Nedenini anladığınızdan emin olun. Çünkü ==karşılaştırma sadece referansları karşılaştırır; equals()yöntem, içeriği bir karakter-karakter karşılaştırma yapar.

Eğer yeni çağırdığınızda ave bher biri yeni bir başvuru aldığını işaret "foo"dize tablosunda. Kaynaklar farklıdır, ancak içerik aynıdır.


128

Evet, kötü ...

==iki dize başvurunuzun tamamen aynı nesne olduğu anlamına gelir. Durum böyle olduğunu duymuş olabilirsiniz, çünkü Java bir çeşit değişmez tablo tutmaktadır (ki bunu yapar), ancak bu her zaman böyle değildir. Bazı dizeler, diğer dizelerden vb. Oluşturulmuş farklı şekillerde yüklenir, bu nedenle iki özdeş dizenin aynı konumda saklandığını asla varsaymamalısınız.

Equals sizin için gerçek karşılaştırmayı yapar.


124

Evet, ==Dizeleri karşılaştırmak kötüdür (kurallı olduklarını bilmiyorsanız gerçekten herhangi bir nesne). ==sadece nesne referanslarını karşılaştırır. .equals()eşitlik testleri. Dizeler için, genellikle aynı olurlar, ancak keşfettiğiniz gibi, bu her zaman garanti edilmez.


118

Java, altında String nesneleri için bellek ayırmayı yöneten bir String havuzuna sahiptir. Java'da String Havuzları konusuna bakın

==İşleç kullanarak iki nesneyi denetlediğinizde (karşılaştırın) , adres eşitliğini dize havuzuyla karşılaştırır. İki String nesnesi aynı adres referanslarına sahipse true, aksi takdirde döndürür false. Ancak iki String nesnesinin içeriğini karşılaştırmak istiyorsanız, equalsyöntemi geçersiz kılmalısınız.

equals aslında Object sınıfının yöntemidir, ancak String sınıfına geçersiz kılınır ve nesnenin içeriğini karşılaştıran yeni bir tanım verilir.

Example:
    stringObjectOne.equals(stringObjectTwo);

Ama unutmayın String örneğine saygı duyar. Büyük / küçük harf duyarsız karşılaştırmak istiyorsanız, String sınıfının equalsIgnoreCase yöntemini kullanmanız gerekir.

Bakalım:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE

7
Bunun büyük soruya geç bir cevap olduğunu görüyorum. Mevcut cevaplarda daha önce bahsedilmeyen ne sağladığını sorabilir miyim?
Gizemli

6
@ Daha equalsIgnoreCasetaze için bilgilendirici olabilecek ekledi .
AmitG

103

Zacherates'in cevabına katılıyorum.

Ancak yapabileceğiniz şey, intern()gerçek olmayan dizelerinizi aramaktır.

Zacherates örneğinden:

// ... but they are not the same object
new String("test") == "test" ==> false 

Stajyer olmayan Dize eşitliği ise true:

new String("test").intern() == "test" ==> true 

8
Bu genellikle iyi bir fikir değildir. Stajyerlik nispeten pahalıdır ve (paradoksal olarak) >> JVM'lerinizin bellek ayak izini artırabilir ve GC maliyetlerini artırabilir. Çoğu durumda, bunlar ==dize karşılaştırması için performans avantajlarından daha ağır basar .
Stephen C

101

==Java'daki nesne başvurularını karşılaştırır ve bu bir istisna değildirString nesneler .

Nesnelerin gerçek içeriklerini (dahil String) karşılaştırmak için , equalsyöntemi kullanmak gerekir .

StringKullanarak iki nesnenin karşılaştırılması ==ortaya çıkarsa true, bunun nedeni Stringnesnelerin stajyedilmiş olması ve Java Sanal Makinesi'nin aynı örneğini gösteren birden fazla referansa sahip olmasıdır String. StringOlarak değerlendirmek için Stringkullanan başka bir nesne ile aynı içeriği içeren bir nesne karşılaştırılması beklenmemelidir .==true


99

.equals()sınıftaki verileri karşılaştırır (işlevin uygulandığı varsayılarak). ==işaretçi konumlarını (nesnenin bellekteki konumu) karşılaştırır.

==her iki nesne de (PRIMITIVES HAKKINDA KONUŞMADIĞINIZ) SAME nesnesi örneğini gösteriyorsa true değerini döndürür. .equals()İki nesne aynı veriler ihtiva ise doğru döndürür equals()Karşı== Java

Bu size yardımcı olabilir.


95

==2 nesnenin (bu durumda dize) bellekteki aynı nesneyi gösterip göstermediğini referans eşitlik denetimi yapar .

equals()Yöntem olmadığını kontrol edecek içeriği ya da durumları 2 nesnelerin aynıdır.

Açıkçası ==daha hızlıdır, ancak sadece 2'lerin Stringaynı metni tutup tutmadığını söylemek istiyorsanız birçok durumda yanlış sonuç verir (olabilir) .

Kesinlikle kullanımı equals() yöntemin kullanılması önerilir.

Performans hakkında endişelenmeyin. Kullanmayı teşvik etmek için bazı şeyler String.equals():

  1. String.equals()Referans eşitliği (kullanarak ==) için ilk kontrollerin uygulanması ve 2 dizge referans olarak aynı ise, başka bir hesaplama yapılmaz!
  2. 2 dize başvurusu aynı değilse, String.equals()daha sonra dize uzunluklarını kontrol eder. Bu aynı zamanda hızlı bir işlemdir çünkü Stringsınıf dizenin uzunluğunu saklar, karakterleri veya kod noktalarını saymaya gerek yoktur. Uzunluklar farklıysa, başka bir kontrol yapılmaz, bunların eşit olamayacağını biliyoruz.
  3. Sadece bu kadar ileri gidersek, 2 dizenin içeriği gerçekten karşılaştırılacak ve bu kısa el karşılaştırması olacak: uyuşmayan bir karakter bulursak (2 dizede aynı konumda) tüm karakterler karşılaştırılamaz ), başka karakter kontrol edilmez.

Her şey söylendiğinde ve yapıldığında, dizelerin stajyer olduklarını garanti etsek bile, equals()yöntemi kullanmak hala birinin düşünebileceği genel yük değil, kesinlikle önerilen yol değildir. Verimli referans kontrolü istiyorsanız, dil belirtimi ve uygulaması tarafından aynı numaralandırma değerinin aynı nesne (referans olarak) olacağı garanti edilen enum'ları kullanın.


2
Obviously == is faster- aslında .equals(String)ilk kontrollerin ==herhangi bir şeyden önce uygulanması, bu yüzden hızın aynı olduğunu söyleyebilirim.
Razzle Shazl

2
public boolean equals(Object anObject) { if (this == anObject) { return true; } ...
Razzle Shazl

82

Benim gibi iseniz, Java'yı ilk kullanmaya başladığımda, iki = örneğinin eşit olup olmadığını test etmek için "==" operatörünü kullanmak istedim, ancak daha iyisi ya da daha kötüsü, Java'da bunu yapmanın doğru yolu değil.

Bu derste, çoğu zaman kullandığım yaklaşımdan başlayarak Java dizelerini doğru bir şekilde karşılaştırmanın birkaç farklı yolunu göstereceğim. Bu Java String karşılaştırma eğitiminin sonunda Java dizelerini karşılaştırırken "==" operatörünün neden çalışmadığını da tartışacağım.

Seçenek 1: eşittir yöntemi ile Java String karşılaştırma Çoğu zaman (belki de% 95) Ben dizeleri Java String sınıfının eşittir yöntemi ile, şöyle:

if (string1.equals(string2))

Bu Dize eşittir yöntemi iki Java dizesine bakar ve tam olarak aynı karakter dizesini içeriyorsa, eşit kabul edilir.

Equals yöntemiyle hızlı bir String karşılaştırma örneğine bakıldığında, aşağıdaki sınama çalıştırıldıysa, karakterler tam olarak aynı olmadığı için iki dize eşit kabul edilmez (karakterlerin durumu farklıdır):

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // java string equals method returns false:
    System.out.println("The two strings are the same.")
}

Ancak, iki dize aynı karakter dizesini içerdiğinde, equals yöntemi bu örnekte olduğu gibi true değerini döndürür:

String string1 = "foo";
String string2 = "foo";

// test for equality with the java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Seçenek 2: equalsIgnoreCase yöntemiyle dize karşılaştırması

Bazı dize karşılaştırma testlerinde, dizelerin büyük veya küçük harf olup olmadığını göz ardı etmek istersiniz. Dizelerinizi bu büyük / küçük harfe duyarlı olmayan bir şekilde eşitlik açısından test etmek istediğinizde, String sınıfının equalsIgnoreCase yöntemini aşağıdaki gibi kullanın:

String string1 = "foo";
String string2 = "FOO";

 // java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

Seçenek 3: CompareTo yöntemiyle Java Dizesi karşılaştırması

Ayrıca Java dizelerini karşılaştırmak için üçüncü, daha az yaygın bir yol vardır ve bu String sınıfı CompareTo yöntemidir. İki dize tamamen aynıysa, CompareTo yöntemi 0 (sıfır) değerini döndürür. İşte bu Dize karşılaştırma yaklaşımının nasıl göründüğüne hızlı bir örnek:

String string1 = "foo bar";
String string2 = "foo bar";

// java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Java'da bu eşitlik kavramı hakkında yazarken, Java dilinin temel Java Nesne sınıfında eşittir bir yöntem içerdiğine dikkat etmek önemlidir. Kendi nesnelerinizi oluşturduğunuzda ve nesnenizin iki örneğinin "eşit" olup olmadığını görmek için bir araç sağlamak istediğinizde, sınıfınızdaki bu eşittir yöntemini geçersiz kılmalı (ve uygulamalısınız) (Java dilinin sağladığı gibi) Dize eşittir yöntemindeki bu eşitlik / karşılaştırma davranışı).

Bu ==, .equals (), CompareTo () ve Compare () ' a bakmak isteyebilirsiniz


5
string değişmezleri için Like String string1 = "foo bar"; String string2 = "foo bar"; içerik eşitliğini test etmek için doğrudan == operatörünü kullanabilirsiniz
JAVA

1
Google apps komut dosyasında "CompareTo" mümkün değildir. Ben instaed "eşittir" denedim Bu çalışan tek çözüm oldu ....
user3887038

77

İşlev:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

Ölçek:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);

6
Bunun diğer cevaplardan farkı nedir? ve neden önerdiğiniz şekilde yapıyorsunuz
user151019 10:15

2
@ Mark arasındaki fark ile ilgili soru ==ve equalsdiğer çözümler zaten cevaplandı, ben sadece dizeleri gevşek bir şekilde karşılaştırmak için farklı bir yol teklif ettim
Khaled.K

77

==Operatör giriş iki referans aynı nesne ya da işaret ediyorsa. .equals()gerçek dize içeriğini (değer) kontrol edin.

.equals()Yöntemin sınıfa ait olduğunu unutmayın Object(tüm sınıfların süper sınıfı). Sınıf gereksiniminize göre geçersiz kılmanız gerekir, ancak Dize için zaten uygulanmıştır ve iki dizenin aynı değere sahip olup olmadığını kontrol eder.

  • Dava 1

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true

    Neden: null olmadan oluşturulan dize değişmezleri, öbek permgen alanındaki String havuzunda saklanır. Yani hem s1 hem de s2 havuzdaki aynı nesneyi gösterir.

  • Durum 2

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true

    Sebep: newAnahtar kelimeyi kullanarak bir String nesnesi oluşturursanız , yığın üzerinde kendisine ayrı bir alan ayrılır.


53

==sınıfta bulunan equals()yöntem nesnenin java.lang.Stringiçeriğini String(başka bir nesneyle) karşılaştırırken, nesnelerin referans değerini karşılaştırır .


15
nit seçici olmamak, ama equals()yöntemi Stringaslında Stringsınıfta, değil Object. Varsayılan equals()içinde Objectiçindekiler aynı olduğunu karşılaştırmak, ve referans aynı olduğunda aslında sadece doğru döndürür olmaz.
Jacob Schoen

1
@JacobSchoen: GrepCode kapalı olduğu için yukarıdaki bağlantı artık çalışmıyor. Eşit uygulama için alternatif: [Inline Link] ( zgrepcode.com/java/openjdk/10.0.2/java.base/java/lang/… )
Amandeep Singh

50

Sanırım bir Stringtanımladığınızda bir nesneyi tanımlarsınız. Yani kullanmalısın.equals() . Kullandığınız ==ancak String(ve herhangi bir nesneyle) ilkel veri türlerini kullanırken kullanmanız gerekir .equals().


7
"char []" ilkel bir veri türü değil! Bu bir dizi "char". Ve diziler kendiliğinden ilkel veri türleri değildir.
Christian

48

Eğer equals()yöntem mevcuttur java.lang.Objectsınıfın ve o nesnelerin devletin denklik kontrol bekleniyor! Bu, nesnelerin içeriği anlamına gelir. Oysa ==operatör kontrol beklenen gerçek nesne örnekleri aynı ya da değildir.

Misal

İki farklı referans değişkeni düşünün str1ve str2:

str1 = new String("abc");
str2 = new String("abc");

Kullanırsanız equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

Çıkışı, TRUEsanki kullandığınız gibi alacaksınız ==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

Şimdi alacak FALSEhem çünkü çıktı olarak str1ve str2her ikisi aynı dize içerik paylaşmasına rağmen, iki farklı nesnelere işaret ediyor. Bunun nedeni new String()her seferinde yeni bir nesnenin yaratılmasıdır.


43

Operator == her zaman nesne referansı karşılaştırması içindir , oysa String sınıfı .equals () yöntemi içerik karşılaştırması için geçersiz kılınır :

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)

40

.equals()Object .equals()bir boole döndüren bir yöntem içerdiğinden, tüm nesnelerin bir yöntemi olduğu garanti edilir . Daha fazla tanımlayıcı bir tanım gerekliyse bu sınıfın geçersiz kılınması alt sınıfın görevidir. O olmadan (yani kullanarak ==), iki nesne arasında sadece bellek adresleri eşitlik açısından kontrol edilir. Dize bunu geçersiz kılar.equals() yöntemi ve bellek adresini kullanmak yerine, eşitlik için karakter düzeyinde dizelerin karşılaştırmasını döndürür.

Önemli bir not, dizelerin bir yumru havuzunda depolanmasıdır, böylece bir dize oluşturulduktan sonra sonsuza kadar aynı adresteki bir programda saklanır. Dizeler değişmez, değişmez. Bu nedenle, ciddi miktarda dize işleme yapıyorsanız, düzenli dize birleştirme kullanmak kötü bir fikirdir. Bunun yerine StringBuildersağlanan sınıfları kullanırsınız . Unutmayın, bu dizgenin göstergeleri değişebilir ve eğer iki göstergenin aynı olup olmadığını görmek isterseniz ==iyi bir yol olabilir. Dizelerin kendileri yoktur.


2
"bir dize oluşturulduktan sonra sonsuza kadar aynı adreste bir programda saklanır" - Bu düz bir yanlıştır. Yalnızca derleme zamanı sabit dize ifadeleri (büyük olasılıkla final Stringdeğişkenleri içerir) ve programınızın açıkça staj yaptığı dizeler "götürü havuzu" olarak adlandırdığınız öğede depolanır. Diğer tüm Stringnesneler gibi, canlı referanslar kalmadığında, diğer tüm nesneler çöp toplama işlemine tabidir. Ayrıca, tüm interning mekanizmasının çalışması için değişmezlik gerekli olmakla birlikte, bununla alakasızdır.
Ted Hopp

Dize karşılaştırması, dizenin içeriğini gerçekten karşılaştıran equals veya equalsIgnoreCase yöntemi ile yapılır. Ancak == işareti sadece referans değerlerini kontrol edin. Dize havuzundan dize değişmezleri için bu durumda iyi çalışır. String s1 = new String ("a"); String s2 = new String ("a"); bu durumda s1 == s2 yanlıştır, ancak s1.equals (s2) doğrudur.
Shailendra Singh

39

compareTo()Yöntemi, iki Dizeyi karşılaştırmak için de kullanabilirsiniz . CompareTo sonucu 0 ise, iki dize eşittir, aksi takdirde karşılaştırılan dizeler eşit değildir.

==Referanslar karşılaştırır ve gerçek dizeleri karşılaştırmak etmez. Her dizeyi kullanarak oluşturduysanız , iki dizeyi karşılaştırmak new String(somestring).intern()için ==işleci kullanabilirsiniz , aksi takdirde equals () veya CompareTo yöntemleri yalnızca kullanılabilir.


35

Java'da “==” operatörü 2 nesneyi karşılaştırmak için kullanıldığında, nesnelerin bellekte aynı yere karşılık gelip gelmediğini kontrol eder. Başka bir deyişle, 2 nesne adının temelde aynı bellek konumuna başvurup başvurmadığını kontrol eder.

Java String sınıfı, Object sınıfındaki varsayılan equals () uygulamasını geçersiz kılar ve yöntemi, bellekteki konumlarını değil, yalnızca dizelerin değerlerini kontrol edecek şekilde geçersiz kılar. Bu, 2 String nesnesini karşılaştırmak için equals () yöntemini çağırırsanız, gerçek karakter dizisi eşit olduğu sürece, her iki nesnenin de eşit olduğu kabul edilir.

==Operatör kontrolleri iki dizeleri tam olarak aynı nesne olup olmadığını.

.equals()Yöntem çek iki dizeleri aynı değeri varsa.


1
bunlardan biri boş değilse, s.equals (s2), s boşsa çökerek karşılaştırmanın başarısız olmasına neden olur. Tabii ki, bu gerçekten cevapla çelişmiyor; bu sadece bir uyarı.
Jon Coombs

1
Hayır, kilitlenmez, bir NullPointerException oluşturur ve karşılaştırmanın gerçekleşmemesine neden olur.
Bludzee
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.