2011-09-20 12 views
9

Powiedzmy, że masz trzy struny,Porównywanie dwóch ciągów znaków z "==": kiedy to zadziała?

String s1 = "string one"; 
String s2 = new String("string one"); 
String s3 = "string one"; 

wiem, że to prawda, że ​​s1 == s2 jest false, ale czytałem gdzieś, że s1 == s3 jest true. Czy to jest poprawne? Dlaczego lub dlaczego nie?

+2

Niezależnie od tego, czy jest to możliwe, czy nie, ale nie powinieneś tego robić.'==' jest dla _obiektowej tożsamości, _ nie porównuje łańcuchów. – paxdiablo

+0

@paxdiablo: Jeśli zajmujesz się wyłącznie literałami ciągów, możesz użyć '=='. Ale dokumentowanie tego jest generalnie takim bólem, że łatwiej jest po prostu użyć 'equals()' na całej tablicy. –

+1

tak, wiem o tym wszystkim. programowałem w Javie od lat i po prostu się zastanawiałem :). nie wygląda na to, że powinno tak być ... –

Odpowiedz

21

Literały łańcuchowe są internowane automatycznie. Stąd s1 == s3 jest prawdziwe. Ciągi mogą być tworzone w puli stałych ciągów lub mogą być tworzone w przestrzeni sterty. Jeśli internujesz ciąg utworzony w stercie, ciąg będzie w stałej puli ciągów.

Podczas tworzenia literału łańcuchowego (String s1 = "ciąg znaków") łańcuch jest tworzony w puli stałej łańcuchowej. Ponadto pula stałych ciągów nie przechowuje duplikatów. Jeśli więc powiesz, że:

String s1 = "string one"; 
String s3 = "string one"; 

Zarówno s1, jak i s3 będą wskazywać na to samo wystąpienie ciągu w puli stałej ciągów. Zatem s1.equals (s3) będzie prawdziwe. I s1 == s3 również jest prawdziwe; ponieważ oba wskaźniki są takie same.

Jednak podczas wystąpienia ciąg przy użyciu „nowych” konstruktor

String s2 = new String("string one"); 

następnie s2 jest tworzone w przestrzeni sterty. Przestrzeń sterty jest innym obszarem pamięci niż stała puli ciągów znaków

Tak więc, podczas gdy s1.equals (s2) ma wartość true, s1 == s2 jest fałszywe; ponieważ będą wskazywać na różne obszary pamięci.

Można jednak skonwertować ciąg utworzony za pomocą "nowego" konstruktora, aby przejść do stałej puli ciągów, wywołując funkcję intern(). Tak więc s2.intern() zwróci ciąg w puli stałej ciąg; chociaż s2 został pierwotnie utworzony w stercie.

+0

Wierzę, że jest to prawdziwe tylko w jednostkach kompilacji? To znaczy, nie uważam, że bardziej ogólne: 'A.x == B.x' jest koniecznie prawdziwe. –

+2

-1 za wprowadzające w błąd, bezsensowne zdanie pierwsze i bez wzmianki o interakcji ciągów. –

+0

@pst: Interpretacja ciągów działa na wszystkich klasach. –

4

Tak, to prawda, ponieważ literały łańcuchowe są internowane. Przeczytaj dokumentację dla String.intern(), aby uzyskać więcej informacji.

W konsekwencji, to wszystko ten sam obiekt (i porówna równym ==):

s1 
s3 
s1.intern() 
s2.intern() 
s3.intern() 
1

powyżej sposób.

i powinieneś wiedzieć dlaczego.

A) ciąg varaible zadeklarowane w kompilacji wg stałej w stałej puli

B) String varaible wyniku metodą ref do obiektu w przestrzeni sterty.

to wszystko ze względu na specyfikację JVM i projekt pamięci.

A) jest, ponieważ łańcuchy są niezmienne. Gdy klasa kompilacji java i klasa obciążenia jvm, jvm znalazła jedną zmienną String zadeklarowaną przez twój czas kodowania, ponieważ jest stała, jvm ustawi stałą na obszarze pamięci "Runtime Constant Pool" . i stała jest wyjątkowa.

B) jest bardzo prosty. ponieważ zmienna runtime jvm używa przestrzeni sterty.

Powiązane problemy