Tôi nên sao chép Chuỗi trong Java như thế nào?


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

Tại thời điểm này, biến dự phòng vẫn chứa giá trị ban đầu "xin chào" (điều này là do tính bất biến của String phải không?).

Nhưng nó có thực sự an toàn khi sao chép Chuỗi bằng phương thức này (tất nhiên là không an toàn để sao chép các đối tượng có thể thay đổi thông thường), hoặc tốt hơn là viết điều này? :

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

Nói cách khác, sự khác biệt (nếu có) giữa hai đoạn trích này là gì?


EDIT - lý do tại sao đoạn trích đầu tiên an toàn:

Hãy để tôi giải thích mọi thứ chi tiết hơn một chút, dựa trên các câu trả lời hay đã được cung cấp (chủ yếu tập trung vào câu hỏi về sự khác biệt về hiệu suất giữa 2 đoạn):

Các chuỗi là bất biến trong Java, có nghĩa là một đối tượng Chuỗi không thể được sửa đổi sau khi xây dựng. Vì thế,

String s = "hello";tạo một cá thể String mới và gán địa chỉ của nó cho s( slà một tham chiếu đến cá thể / đối tượng)

String backup_of_s = s;tạo một biến mới backup_of_svà khởi tạo nó để nó tham chiếu đến đối tượng hiện được tham chiếu bởi s.

Lưu ý: Tính không thay đổi của chuỗi đảm bảo rằng đối tượng này sẽ không bị sửa đổi: bản sao lưu của chúng tôi an toàn

Lưu ý 2: Cơ chế thu gom rác Java đảm bảo rằng đối tượng này sẽ không bị hủy miễn là nó được tham chiếu bởi ít nhất một biến ( backup_of_strong trường hợp này)

Cuối cùng, s = "bye";tạo một thể hiện Chuỗi khác (vì tính bất biến, đó là cách duy nhất) và sửa đổi sbiến để bây giờ nó tham chiếu đến đối tượng mới.

Câu trả lời:


139

Vì các chuỗi là bất biến, cả hai phiên bản đều an toàn. Tuy nhiên, cái sau thì kém hiệu quả hơn (nó tạo ra một đối tượng phụ và trong một số trường hợp sao chép dữ liệu ký tự).

Với suy nghĩ này, phiên bản đầu tiên nên được ưu tiên.


15
Bất biến không có gì để làm với nó. Nó chỉ đơn giản là cách các tài liệu tham khảo đối tượng hoạt động. Tôi có thể cung cấp một ví dụ StringBuilder tương đương.
GriffeyDog

1
@BalusC, tôi không thể thấy String () mới có thể tạo bất cứ thứ gì trong nhóm Chuỗi của JVM. Chỉ những người xả rác chuỗi và những người được cam kết vào hồ bơi thông qua intern () mới ở trong hồ bơi.
Snicolas

3
@GriffeyDog: Tôi đang đọc câu hỏi ít hơn theo nghĩa đen. Điều tôi đang nói là an toàn khi đưa ra các tham chiếu đến một đối tượng chuỗi mà không sợ ai đó có thể sửa đổi chuỗi.
NPE

2
@GriffeyDog Tôi thấy nhận xét của bạn rất sai lệch: tính bất biến là điều làm cho đoạn trích đầu tiên an toàn, tại sao bạn lại nói nó không liên quan gì đến "nó"?
Sébastien

5
@Sebastien Tất cả những gì nó làm là gán lại biến tham chiếu sđể tham chiếu đến một đối tượng khác ( String"tạm biệt"). Điều đó không ảnh hưởng đến những gì mà biến tham chiếu backup_of_sđang đề cập đến ( String"xin chào"). Như tôi đã nói, tôi có thể cung cấp một ví dụ tương đương với StringBuilders, không phải là bất biến. Nhận xét của tôi chủ yếu liên quan đến câu lệnh OP: Tại thời điểm này, biến dự phòng vẫn chứa giá trị ban đầu "xin chào" (điều này là do tính bất biến của String phải không?).
GriffeyDog

22

Chuỗi là các đối tượng bất biến để bạn có thể sao chép chúng chỉ cần đối phó với tham chiếu đến chúng, vì đối tượng được tham chiếu không thể thay đổi ...

Vì vậy, bạn có thể sao chép như trong ví dụ đầu tiên của mình mà không gặp vấn đề gì:

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

10

Phiên bản thứ hai của bạn kém hiệu quả hơn vì nó tạo ra một đối tượng chuỗi bổ sung khi đơn giản là không cần phải làm như vậy.

Tính không thay đổi có nghĩa là phiên bản đầu tiên của bạn hoạt động theo cách bạn mong đợi và do đó là cách tiếp cận được ưa thích.


0

Trường hợp thứ hai cũng không hiệu quả về mặt chuỗi String, bạn phải gọi rõ ràng intern () trên tham chiếu trả về để làm cho nó thực tập.


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

Làm thế nào về bản sao như thế này? Tôi nghĩ rằng để có được một bản sao mới là tốt hơn, để dữ liệu của str1sẽ không bị ảnh hưởng khi str2được tham chiếu và sửa đổi trong hành động xa hơn.


3
Stringlà bất biến. Chuỗi nhân bản không có ý nghĩa nhiều.
Vladimir
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.