2010-09-11 10 views
9

Powiel możliwe:
What makes reference comparison (==) work for some strings in Java?Korzystanie '==' zamiast .equals ciągów Java

wiem, że to nie było asked before, ale mimo zaleceń używać zamiast .equals() operator porównania ==, stwierdziłem, że == działa cały czas:

String s1 = "Hello"; 
String s2 = "Hello"; 
System.out.println(s1 == s2); // true 

Czy ktoś może podać przykład operatora ==, który nie działa?

+0

Marcos warunkiem dobrego przykładu [] (http://stackoverflow.com/questions/767372/java-string-equals-versus/1251721#1251721) w odpowiedzi na pytania, które powiązane. –

+0

Powiązane: http://stackoverflow.com/questions/9698260/what-makes-reference-comparison-work-for-some-strings-in-java/9698305#9698305 – berry120

Odpowiedz

37

To dlatego, że jesteś szczęśliwy. Operator == w Javie sprawdza dla równanie odniesienia: zwraca wartość true, jeśli wskaźniki są takie same. Nie sprawdza równości zawartości. Identyczne łańcuchy znalezione podczas kompilacji są zwinięte w pojedynczą instancję String, więc działa z literałami String, ale nie z ciągami generowanymi w środowisku wykonawczym.

Na przykład "Foo" == "Foo" może działać, ale "Foo" == new String("Foo") nie będzie, bo new String("Foo") tworzy nową instancję String, i łamie wszelkie możliwe równości wskaźnika.

Co ważniejsze, większośćStrings, z którymi radzisz sobie w realnym świecie, generowane są w środowisku wykonawczym. Wprowadzane przez użytkownika w polach tekstowych jest generowane przez środowisko wykonawcze. Wiadomości odbierane przez gniazdo są generowane przez środowisko wykonawcze. Rzeczy odczytane z pliku są generowane przez środowisko wykonawcze. Dlatego bardzo ważne jest, aby użyć metody equals, a nie operatora ==, jeśli chcesz sprawdzić równość zawartości.

+3

Trochę dodatkowej nocie, powód „foo” == „foo” faktycznie działa, dlatego wszystkie dosłowne ciągi są internowany http: // pobierz .oracle.com/JavaSE/1.4.2/docs/api/java/lang/String.html # intern() –

9

Czy ktoś może podać mi przykład operatora ==?

Przykład 1:

String s1 = new String("Hello"); 
String s2 = new String("Hello"); 
System.out.println(s1 == s2); // false 

Przykład 2:

Integer a=1000,b=1000; 
System.out.println(a == b); // false 
+1

Guess, że będzie działać. Ale czy Strings nie są niezmienne? Czy nie powinni być internowani? – Aillyn

+0

Łańcuchy literowe są internowane. –

+1

"Cześć" == "Cześć" ==> prawda. Jednak nowy ciąg ("Hello") przydzieli trochę pamięci dla obiektu, a to samo ponownie przydzieli trochę więcej pamięci, w innym miejscu, na inny obiekt. Ponieważ operator "==" porównuje odniesienia, zwróci wartość false. –

4

Kiedy to zrobisz, jesteś rzeczywiście tworzenie ciąg literały:

String s1 = "Hello"; 
String s2 = "Hello"; 

Kompilator znajdzie literały identyczny ciąg, a następnie optymalizuje utrzymując jedno wystąpienie w stercie i podejmowania wszystkich zmiennych w punkcie stosu do tego. Tak więc wykonanie == zwróci true, ponieważ wskazują one ten sam adres pamięci.

Gdy to zrobisz, tworzysz ciąg obiektów:

String s1 = new String("Hello"); 
String s2 = new String("Hello"); 

konkretyzacją stworzy unikalną przestrzeń na stercie dla każdej z tych zmiennych i stos będzie wskazywać na tych odrębnych lokalizacjach. Zatem będą one równe przy użyciu .equals(), ponieważ ich wartości są takie same, ale nie będą równe przy użyciu ==, ponieważ są to różne obiekty w przestrzeni pamięci sterty.

4

Doświadczeni programiści Java rzadko, jeśli kiedykolwiek użyć new String(String), ale problem pojawia się w innych przypadkach, jak również. Na przykład:

String hello = "Hello" 
String hell = hello.substring(0, 4); 
System.err.println("Hell" == hell); // should print "false". 

(większości przypadków ciąg w rzeczywistych aplikacjach powstają albo w drodze podciąg jakiegoś innego String, lub konstruując go z tablicy znaków Bardzo niewiele aplikacji użyje tylko instancje String. stworzony jako literały.)

+1

jeden powód, aby użyć "y = new String (x)" (gdzie x jest ciągiem) jest umożliwienie garbage collection, gdy x jest podciągiem bardzo dużego ciągu. Jeśli po prostu użyjesz "y = x", to bardzo duży ciąg nie może uzyskać zbierania śmieci, o ile odwołuje się do y. Jeśli użyjesz "nowego ciągu (x)", tworzony jest nowy ciąg, który nie odwołuje się do oryginalnego dużego ciągu. –

+4

To prawda, ale z mojego doświadczenia jest to rzadko konieczne. A jeśli nie jest to konieczne, to w rzeczywistości jest to antyoptymalizacja. –

Powiązane problemy