2010-10-27 27 views
13

Như đã nói, toán tử == so sánh các tham chiếu đối tượng để kiểm tra xem chúng có đang đề cập đến cùng một đối tượng trên một đống hay không. Nếu vậy tại sao tôi nhận được "Bình đẳng" cho đoạn mã này?Nếu == so sánh các tham chiếu trong Java, tại sao nó lại đánh giá đúng với các chuỗi này?

public class Salmon { 
    public static void main(String[] args) { 

     String str1 = "Str1"; 
     String str2 = "Str1"; 

     if (str1 == str2) { 
      System.out.println("Equal"); 
     } else { 
      System.out.println("Not equal"); 
     } 
    } 
} 
+1

bạn có chắc là bạn đã sử dụng '==' hoặc '=' ?? –

+0

Đã thay đổi ví dụ về mã, xin lỗi – Eugene

+1

Hãy chắc chắn nói ngôn ngữ là JAVA. Các ngôn ngữ khác sẽ có triển khai khác. Dù toán tử == bị quá tải để làm cho .net. – CodingBarfield

Trả lời

37

Chương trình sẽ in Equal. (Ít nhất bằng cách sử dụng Sun Hotspot và Suns Javac.) Ở đây nó được thể hiện trên http://ideone.com/8UrRrk

Điều này là do thực tế là các hằng chuỗi literal được lưu trữ trong một hồ bơi chuỗi và chuỗi tham chiếu thể được tái sử dụng .

Đọc thêm:


Tuy nhiên điều này:

public class Salmon { 
    public static void main(String[] args) { 

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

     if (str1 == str2) { 
      System.out.println("Equal"); 
     } else { 
      System.out.println("Not equal"); 
     } 
    } 
} 

Sẽ in Not equal từ new được đảm bảo giới thiệu một tham chiếu mới.

Vì vậy, quy tắc chung: Luôn so sánh các chuỗi bằng phương pháp equals.

+0

+1 để liên kết với ideone.com. Tôi muốn một webapp như thế này trong một thời gian dài. Ngay cả nghĩ về việc viết nó cho bản thân mình nhưng có nó. –

+3

Để hoàn thành 'chuỗi mới (" Str1 "). Intern()' sẽ in "Bằng" cũng :) – OscarRyz

+0

@OscarRyz, Điểm tốt. Cảm ơn! :-) – aioobe

3

Mã này sẽ không in Equal.
Nhưng nếu hai dây là như nhau, trường hợp này sẽ là đặc biệt.

Bây giờ bạn đã được cập nhật mã của bạn, nó là trường hợp:

Một đơn giản (nhưng không hoàn toàn chính xác) giải thích là trình biên dịch thấy rằng hai chuỗi đều giống nhau và làm điều gì đó như:

String str1 = "Str1"; 
String str2 = str1; 

Điều gì thực sự xảy ra ở đây là trình biên dịch sẽ thấy những chuỗi chữ và đặt nó trong "hồ bơi literal string".

Như một chuỗi không thể sửa đổi (nó không thay đổi) các giá trị bằng chữ của chuỗi (được tìm thấy trong quá trình biên dịch) được đặt trong một "hồ bơi".
Bằng cách này, nếu hai chuỗi chữ khác nhau có cùng nội dung (như trong trường hợp cụ thể này), bộ nhớ không bị lãng phí để lưu trữ "Str1" và "Str1" hai lần.

+0

Tôi xin lỗi, tôi đã thêm sửa chữa cho ví dụ mã. – Eugene

3

Java lưu trữ tất cả các chuỗi trong bảng chuỗi nội bộ trong khi chạy. Các tham chiếu đến hai chuỗi là giống nhau vì trong bộ nhớ chúng được lưu trữ ở cùng một vị trí. Do đó, Equal.

Tuyên bố của bạn là đúng, rằng == so sánh các tham chiếu đối tượng. Hãy thử điều tương tự với bất kỳ lớp nào khác nhưng Strings và bạn sẽ không nhận được kết quả tương tự.

+0

Nó có? bạn có thể cho tôi một tham chiếu để trả lại yêu cầu này không? –

+1

aioobe đưa ra giải thích tốt hơn vì hành vi này không được đảm bảo. Và nó cũng chỉ áp dụng cho các chuỗi ký tự, không phải cho mọi chuỗi trong một chương trình. – Joey

+2

Từ các tài liệu API Java: "Tất cả các chuỗi ký tự và các biểu thức hằng số có giá trị chuỗi được thực tập." Xem http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern%28%29 Lưu ý rằng chỉ các chuỗi không đổi sẽ được tự động thực hiện. Bạn có thể tạo các chuỗi động bằng thực tế bằng cách bắt buộc String.intern() –

0

Nhận xét ở trên đã tóm tắt khá tốt.

Tôi không có môi trường Java tiện dụng, nhưng việc cố gắng sau đây sẽ làm rõ mọi thứ cho bạn (hy vọng điều này hoạt động như tôi dự đoán).

String str1 = "Str1"; 
String str2 = "Str"; str2 += "1"; 

Nên bây giờ in Không bằng

2

dân, bạn đang quên rằng quá trình đặt chuỗi chữ trong hồ bơi được gọi là "thực tập". Lớp String có một phương thức gọi là intern(). Phương pháp này đặt bất kỳ chuỗi vào hồ bơi, ngay cả khi nó không phải là trong hồ bơi ban đầu (không phải chữ). Điều này có nghĩa là mã như sau:

String a = "hello"; 
String b = new String("hello"); 
b = b.intern(); 

System.out.println(a == b); 

sẽ in "true". Bây giờ, tại sao một người nào đó cần điều này? Như bạn có thể tưởng tượng, so sánh chuỗi a.equals(b) có thể mất nhiều thời gian nếu các chuỗi có cùng độ dài nhưng khác nhau gần cuối. (Chỉ cần nhìn vào mã nguồn .equals().).

Tuy nhiên, việc so sánh các tham chiếu trực tiếp giống như so sánh các số nguyên (con trỏ trong C nói), gần như ngay lập tức.

Vì vậy, điều này cung cấp cho bạn điều gì? Tốc độ. Nếu bạn phải so sánh cùng một chuỗi nhiều, nhiều lần, hiệu suất chương trình của bạn sẽ được hưởng lợi rất nhiều nếu bạn thực hiện các chuỗi này. Tuy nhiên, nếu bạn sẽ so sánh các chuỗi chỉ một lần, sẽ không có hiệu năng đạt được khi quá trình interning tự sử dụng equals().

Tôi hy vọng điều này sẽ giải thích điều này.

cảm ơn

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