2012-03-14 23 views
52

Tôi có các dòng mã sau để so sánh Chuỗi. str1 không bằng str2, có thể hiểu được vì nó so sánh tham chiếu đối tượng. Nhưng tại sao s1 bằng s2?Điều gì làm cho so sánh tham chiếu (==) hoạt động đối với một số chuỗi trong Java?

String s1 = "abc"; 
String s2 = "abc"; 

String str1 = new String("abc"); 
String str2 = new String("abc"); 

if (s1==s2) 
    System.out.println("s1==s2");   
else 
    System.out.println("s1!=s2"); 

if (str1==str2) 
    System.out.println("str1==str2");   
else 
    System.out.println("str1!=str2"); 

if (s1==str1) 
    System.out.println("str1==s1");   
else 
    System.out.println("str1!=s1"); 

Output:

s1==s2 
    str1!=str2 
    str1!=s1 
+12

Bạn đã thử tìm kiếm SO đầu tiên? :( –

+13

http://stackoverflow.com/questions/7144059/java-string-pool-object-creation, http://stackoverflow.com/questions/4033625/if-compares-references-in-java-why-does -it-evaluation-to-true-with-these-strin, http://stackoverflow.com/questions/6377058/string-reference, http://stackoverflow.com/questions/1903094/java-strings-and-stringpool –

+1

(Tôi không đóng này, bởi vì tôi đã không tìm thấy một câu hỏi khác * như tập trung * như thế này, nhưng tôi chắc chắn nó tồn tại) –

Trả lời

80

Chuỗi hồ bơi liên tục về cơ bản sẽ cache tất cả các xâu vì vậy họ đang cùng một đối tượng bên dưới, đó là lý do mà bạn nhìn thấy đầu ra bạn làm cho s1==s2. Về cơ bản nó là một sự tối ưu hóa trong máy ảo để tránh tạo một đối tượng chuỗi mới mỗi khi một chữ được khai báo, điều này có thể rất tốn kém rất nhanh! Với ví dụ str1==str2 của bạn, bạn đang nói rõ với máy ảo để tạo các đối tượng chuỗi mới, do đó tại sao nó sai.

Là một sang một bên, gọi phương thức intern() trên bất kỳ chuỗi nào sẽ thêm nó vào nhóm không đổi (và trả về chuỗi mà nó được thêm vào hồ bơi.) Không nhất thiết phải làm điều này, trừ khi bạn chắc chắn bạn đang xử lý các chuỗi mà chắc chắn sẽ được sử dụng như hằng số, nếu không bạn có thể sẽ tạo ra khó khăn để theo dõi rò rỉ bộ nhớ.

+2

Bạn đánh bại tôi chỉ trong 2 giây cho ý tưởng phương thức intern() –

+6

Bạn tạm ẩn bạn mất. haha ​​j/k. = P –

+1

+1 nhưng cũng đáng chú ý là việc thêm nhiều chuỗi vào nhóm không đổi nói chung là một ý tưởng tồi vì nó có thể gây ra rò rỉ bộ nhớ khó phát hiện. Chỉ thực hiện việc này cho một số lượng nhỏ cố định các Chuỗi thực sự sẽ được sử dụng làm hằng số (ví dụ: các khóa HashMap), không bao giờ cho dữ liệu Chuỗi tùy ý. – mikera

18

s1 và s2 là các chuỗi ký tự. Khi bạn tạo một chuỗi ký tự mới, trình biên dịch đầu tiên sẽ kiểm tra xem có bất kỳ chữ cái nào đại diện giống nhau có trong nhóm String hay không. Nếu có một trình bày, trình biên dịch trả về bằng chữ nếu không thì trình biên dịch sẽ tạo ra một trình biên dịch mới.

Khi bạn tạo chuỗi s2 trình biên dịch trả về Chuỗi s1 từ hồ bơi như đã được tạo trước đó. Đó là lý do tại sao s1s2 giống nhau. Hành vi này được gọi là thực tập.

+0

Tôi hơi bối rối khi bạn nói rằng "trình biên dịch tạo ra một cái mới". AFAIK, trình biên dịch có nghĩa là để tạo mã máy trung gian và không thực sự chạy (do đó tạo ra) bất kỳ đối tượng nào trong bộ nhớ. Bạn có nghĩa là trình biên dịch _replaces_ chuỗi chữ? Vui lòng làm rõ điều này. – peakit

+0

Tôi không có bất kỳ tài liệu hỗ trợ nào ngay bây giờ, nhưng tôi tin @Chandra Sekhar đã đề cập đến trình biên dịch JIT hoặc Just In Time và không phải trình biên dịch javac. – Robert

3

Trong Java, các chuỗi không đổi giống nhau sẽ được sử dụng lại. Vì vậy, s1s2 trỏ đến cùng một đối tượng "abc" và s1==s2. Nhưng khi bạn sử dụng new String("abc"), một đối tượng khác sẽ được tạo. Vì vậy, s1 != str1.

5

Điều này là do các chuỗi ký tự được tập trung. Về vấn đề này, Java documentations nói:

Tất cả các chuỗi chữ và chuỗi giá trị biểu thức hằng số là thực tập nội trú

Và điều này giải thích tại sao s1s2 đều giống nhau (hai biến trỏ đến cùng một thực tập nội trú chuỗi)

9

Hiện tượng này là do String interning.

Về cơ bản, tất cả các chuỗi ký tự là "được lưu trong bộ nhớ cache" và được sử dụng lại.

0

string không thay đổi trong java, tất cả các string literals được lưu vào bộ nhớ cache để có thể sử dụng lại.

Khi bạn tạo đối tượng String bằng toán tử new(), nó luôn tạo đối tượng mới trong bộ nhớ heap. Mặt khác, nếu bạn tạo đối tượng bằng cách sử dụng cú pháp văn bản chuỗi, ví dụ:"Java", nó có thể trả về một đối tượng hiện có từ String pool (một bộ nhớ cache của String object trong không gian gen Perm, mà bây giờ được chuyển đến không gian heap trong bản phát hành Java gần đây), nếu nó đã tồn tại. Nếu không, nó sẽ tạo một đối tượng chuỗi mới và đặt vào nhóm chuỗi để sử dụng lại trong tương lai.

String s1 = new String("java"); 
String s2 = new String("java"); 
String s3 = "java"; 
String s4 = "java"; 

enter image description here

Please refer this link

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