2013-01-23 34 views
10

Câu hỏi đặt ra sôi xuống mã này:Thực tập chuỗi Java, điều gì được đảm bảo?

// setup 
String str1 = "some string"; 
String str2 = new String(str1); 
assert str1.equals(str2); 
assert str1 != str2; 
String str3 = str2.intern(); 

// question cases 
boolean case1 = str1 == "some string"; 
boolean case2 = str1 == str3; 

Liệu tiêu chuẩn Java đưa ra bất cứ đảm bảo về giá trị của case1case2? Liên kết đến một phần liên quan của đặc tả Java sẽ là tốt đẹp, tất nhiên.

Có, tôi đã xem tất cả "Câu hỏi tương tự" do SO tìm thấy và không tìm thấy bản sao nào, vì không có gì tôi tìm thấy đã trả lời câu hỏi theo cách này. Và không, đây không phải là ý tưởng sai lầm về việc so sánh chuỗi "tối ưu hóa" bằng cách thay thế equals bằng ==.

+2

Nếu nó không phải là một nỗ lực tối ưu hóa vô dụng, nó là gì? –

+0

@dystroy Trường hợp cụ thể mà tôi đã có về việc sử dụng tên tệp đã được chuẩn hóa để đồng bộ hóa và nếu chuỗi nội bộ được an toàn cho mục đích, hoặc nếu một 'Map fileNameToLockObjectMap' được chia sẻ sẽ là cần thiết. Không chắc chắn, tôi đã sử dụng Bản đồ trong trường hợp đó (và sẽ không quay lại thay đổi). – hyde

+0

Khóa trên các chuỗi nội bộ không phải là một ý tưởng hay. Rất có thể bạn sẽ có những hậu quả không mong muốn. –

Trả lời

13

Đây là JLS báo giá của bạn, Section 3.10.5:

Mỗi chuỗi chữ là một tài liệu tham khảo (§4.3) đến một instance (§4.3.1, §12.5) của lớp String (§4.3.3) . Đối tượng chuỗi có giá trị không đổi. Chuỗi ký tự - hoặc, nói chung, các chuỗi là các giá trị của các biểu thức không đổi (§15.28) -are "interned" để chia sẻ các trường hợp độc đáo, sử dụng phương thức String.intern.

Như vậy, chương trình thử nghiệm bao gồm các đơn vị biên dịch (§7.3):

package testPackage; 
class Test { 
     public static void main(String[] args) { 
       String hello = "Hello", lo = "lo"; 
       System.out.print((hello == "Hello") + " "); 
       System.out.print((Other.hello == hello) + " "); 
       System.out.print((other.Other.hello == hello) + " "); 
       System.out.print((hello == ("Hel"+"lo")) + " "); 
       System.out.print((hello == ("Hel"+lo)) + " "); 
       System.out.println(hello == ("Hel"+lo).intern()); 
     } 
} 

class Other { static String hello = "Hello"; } 

và các đơn vị biên soạn:

package other; 

public class Other { static String hello = "Hello"; } 

sẽ cho kết quả: đúng true true true true

Ví dụ này minh họa sáu điểm:

Chuỗi ký tự trong cùng một lớp (§8) trong cùng một gói (§7) đại diện cho cùng một đối tượng String (§4.3.1).

Chuỗi ký tự trong các lớp khác nhau trong cùng một gói đại diện cho các tham chiếu cho cùng một đối tượng Chuỗi.

Chuỗi ký tự trong các lớp khác nhau trong các gói khác nhau tương tự như vậy đại diện cho tham chiếu đến cùng một đối tượng Chuỗi.

Các chuỗi được tính theo biểu thức hằng số (§15.28) được tính tại thời gian biên dịch và sau đó được xử lý như thể chúng là chữ.

Các chuỗi được tính bằng cách ghép nối tại thời gian chạy mới được tạo và do đó khác biệt. Kết quả của việc thực hiện một cách rõ ràng một chuỗi được tính toán là cùng một chuỗi như bất kỳ chuỗi ký tự có sẵn nào với nội dung giống nhau.

Kết hợp với số JavaDoc để thực tập và bạn có đủ thông tin để suy luận rằng cả hai trường hợp của bạn sẽ trả về giá trị thực.

+0

Làm thế nào nó hoạt động trong môi trường đa luồng, ví dụ. khi intern() là callad nhiều lần từ nhiều chủ đề cùng một lúc. Tôi đoán rằng điều này được quan tâm, nhưng đó chỉ là một phỏng đoán. Bạn có biết thêm về điều này? – Alpedar

+2

@Alpedar - việc triển khai thực tập là bản địa và nền tảng phụ thuộc. Tôi đoán nó là chủ đề an toàn dựa trên JavaDoc, nhưng họ không đảm bảo (mà tôi đã tìm thấy) trong tài liệu chính thức sao lưu này lên. – Perception

5

Tôi nghĩ String.intern API cung cấp đủ thông tin

Một nhóm dây, lúc đầu trống, được duy trì riêng bởi chuỗi lớp.

Khi phương thức thực thi được gọi, nếu nhóm đã chứa chuỗi bằng đối tượng String này được xác định bằng phương thức equals (Object), thì chuỗi từ pool được trả về. Nếu không, đối tượng String này được thêm vào pool và tham chiếu đến đối tượng String này được trả về.

Sau đó, đối với bất kỳ hai chuỗi s và t, s.intern() == t.intern() là đúng nếu và chỉ khi s.equals (t) là đúng.

Tất cả các chuỗi chữ và các biểu thức hằng số có giá trị chuỗi được thực tập. Các chuỗi ký tự được định nghĩa trong phần 3.10.5 của Đặc tả Ngôn ngữ Java ™.

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