Jak mam skopiować ciągi znaków w Javie?


199
    String s = "hello";
    String backup_of_s = s;
    s = "bye";

W tym momencie zmienna zapasowa nadal zawiera oryginalną wartość „hello” (jest to spowodowane niezmiennością ciągu String, prawda?).

Ale czy naprawdę bezpiecznie jest kopiować ciągi za pomocą tej metody (co oczywiście nie jest bezpieczne, aby kopiować zwykłe zmienne obiekty), czy lepiej to napisać? :

    String s = "hello";
    String backup_of_s = new String(s);
    s = "bye";

Innymi słowy, jaka jest różnica (jeśli w ogóle) między tymi dwoma fragmentami?


EDYCJA - powód, dla którego pierwszy fragment jest bezpieczny:

Pozwólcie, że wyjaśnię to trochę bardziej szczegółowo, w oparciu o już udzielone dobre odpowiedzi (które zasadniczo koncentrowały się na kwestii różnicy wydajności między 2 fragmentami):

Ciągi są niezmienne w Javie, co oznacza, że ​​obiektu String nie można modyfikować po jego budowie. W związku z tym,

String s = "hello";tworzy nową instancję String i przypisuje jej adres s( sbędący odwołaniem do instancji / obiektu)

String backup_of_s = s;tworzy nową zmienną backup_of_si inicjuje ją, aby odwoływała się do obiektu, do którego aktualnie się odwołuje s.

Uwaga: Niezmienność łańcucha gwarantuje, że ten obiekt nie zostanie zmodyfikowany: nasza kopia zapasowa jest bezpieczna

Uwaga 2: Mechanizm czyszczenia pamięci w Javie gwarantuje, że ten obiekt nie zostanie zniszczony, dopóki będzie do niego odwoływała przynajmniej jedna zmienna ( backup_of_sw tym przypadku)

Na koniec s = "bye";tworzy kolejną instancję String (ze względu na niezmienność, jest to jedyny sposób) i modyfikuje szmienną, aby teraz odwoływała się do nowego obiektu.

Odpowiedzi:


141

Ponieważ ciągi są niezmienne, obie wersje są bezpieczne. Ten ostatni jest jednak mniej wydajny (tworzy dodatkowy obiekt, a w niektórych przypadkach kopiuje dane postaci).

Mając to na uwadze, należy preferować pierwszą wersję.


15
Niezmienność nie ma z tym nic wspólnego. Po prostu działają odwołania do obiektów. Mógłbym podać równoważny przykład StringBuilder.
GriffeyDog

1
@BalusC, nie widzę, jak nowy String () mógłby stworzyć cokolwiek w puli String JVM. W puli znajdują się tylko literały łańcuchowe i te przypisane do puli przez intern ().
Snicolas

3
@GriffeyDog: Czytam pytanie mniej dosłownie. Mówię o tym, że można bezpiecznie podawać odniesienia do obiektu łańcucha bez obawy, że ktoś może zmodyfikować łańcuch.
NPE

2
@GriffeyDog Twój komentarz jest bardzo mylący: niezmienność sprawia, że ​​pierwszy fragment jest bezpieczny, dlaczego miałbyś powiedzieć, że nie ma on nic wspólnego z „nim”?
Sébastien

5
@Sebastien Wszystko, co robi, to ponowne przypisanie zmiennej referencyjnej sdo odwołania do innego obiektu ( String„pa”). Nie ma to wpływu na to, do czego odnosi się zmienna referencyjna backup_of_s( String„cześć”). Jak powiedziałem, mógłbym podać równoważny przykład z StringBuilders, które nie są niezmienne. Mój komentarz dotyczy głównie instrukcji OP: w tym momencie zmienna zapasowa nadal zawiera oryginalną wartość „hello” (czy to z powodu niezmienności ciągu String?).
GriffeyDog

22

Ciągi są niezmiennymi obiektami, więc możesz je skopiować, po prostu kopiując do nich odwołanie, ponieważ odwołany obiekt nie może się zmienić ...

Możesz więc bez problemu kopiować jak w pierwszym przykładzie:

String s = "hello";
String backup_of_s = s;
s = "bye";

10

Druga wersja jest mniej wydajna, ponieważ tworzy dodatkowy obiekt łańcuchowy, gdy po prostu nie ma takiej potrzeby.

Niezmienność oznacza, że ​​Twoja pierwsza wersja zachowuje się tak, jak się spodziewasz, a zatem jest to preferowane podejście.


0

Drugi przypadek jest również nieefektywny pod względem puli ciągów, musisz jawnie wywołać intern () po powrocie odwołania, aby uczynić go internem.


-16
String str1="this is a string";
String str2=str1.clone();

Co powiesz na taką kopię? Myślę, że lepsze jest uzyskanie nowej kopii, aby dane str1nie uległy zmianie, gdy str2zostaną odwołane i zmodyfikowane w dalszej akcji.


3
Stringjest niezmienny. klonowanie strun nie ma większego sensu.
Vladimir
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.