2012-05-15 29 views
137
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 "hello" (điều này là do quyền không thay đổi của String?).Tôi nên sao chép Strings bằng Java như thế nào?

Nhưng thực sự là an toàn để sao chép chuỗi bằng phương pháp 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 xuyên) hay viết tốt hơn? :

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 mã này là gì?


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

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

Chuỗi không thay đổi trong Java, điều này có nghĩa là đối tượng String không thể sửa đổi sau khi xây dựng. Do đó,

String s = "hello"; tạo một String dụ mới và gán địa chỉ của nó để s (s là một tham chiếu đến dụ/object)

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

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

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

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

Trả lời

94

Vì chuỗi không thay đổi được, cả hai phiên bản đều an toàn. Cái thứ hai, tuy nhiên, 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 ý nghĩ này, bạn nên sử dụng phiên bản đầu tiên.

+11

Tính bất biến không liên quan gì đến nó. Nó chỉ đơn giản là cách tham chiếu đố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 cách String mới() có thể tạo bất kỳ thứ gì trong nhóm Chuỗi của JVM. Chỉ có các chuỗi rác và những người được cam kết vào hồ bơi thông qua thực tập() có trong hồ bơi. – Snicolas

+2

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

9

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 thừa khi đơn giản là không cần phải làm như vậy.

Tính bất biến 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 ưu tiên.

12

Chuỗi là immutable objects để bạn có thể sao chép chúng chỉ đối chiếu tham chiếu với 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 bạn mà không cần bất kỳ vấn đề:

String s = "hello"; 
String backup_of_s = s; 
s = "bye"; 
-10
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 bản sao mới tốt hơn, sao cho dữ liệu của str1 sẽ không bị ảnh hưởng khi str2 được tham chiếu và sửa đổi trong hành động khác.

+3

'Chuỗi' là không thay đổi. nhân bản Strings không có ý nghĩa nhiều. – Vladimir

+11

'String.clone()' thậm chí không tồn tại ... – glen3b

0

Trường hợp thứ hai cũng không hiệu quả về nhóm Chuỗi, 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.

Các vấn đề liên quan