2011-09-26 24 views
6

thể trùng lặp:
If == compares references in Java, why does it evaluate to true with these Strings?
String comparision with logical operator in Javachuỗi "==" trong java kiểm tra tham chiếu, tại sao mã này trả về true?

public static void main(String[] args) 
{ 
    String a = "ab"; 
    final String bb = "b"; 
    String b = "a" + bb; 
    System.out.println(a == b); 
} 

tại sao nó in đúng ??

nhưng,

public static void main(String[] args) 
{ 
    String a = "ab"; 
    String bb = "b"; 
    String b = "a" + bb; 
    System.out.println(a==b); 
} 

nó in sai.

Trả lời

6

Bạn đang nhìn thấy kết quả của hai điều làm việc kết hợp:

  1. Trình biên dịch được xử lý "a" + bb tại thời gian biên dịch chứ không phải chạy, vì bbfinal và để nó biết nó có thể làm cái đó. (Có những lúc khác cũng biết điều đó.)

  2. Tất cả các chuỗi được tạo bởi trình biên dịch là interned.Để biết thêm về thực tập, hãy xem this answer đến một câu hỏi StackOverflow khác về == trong Java.

Vì vậy, kết quả là ab trỏ đến chuỗi Ví dụ cùng, và do đó lợi nhuận ==true.

6

Trình biên dịch tính chuỗi tại thời gian biên dịch vì nó là cuối cùng và sẽ không bao giờ thay đổi.

final String bb = "b"; 
String b = "a" + bb; 

"a" + bb được đánh giá tại thời gian biên dịch

+0

... là một nửa câu trả lời ... ;-) –

5

Java sẽ hằng tập string (chuỗi thức) và literals (tạo một thể hiện của mỗi chuỗi trong một hồ bơi nội bộ) và do đó bạn có thể nhận được cùng một ví dụ, ngay cả nếu nó được "tạo ra" bằng cách nối.

Và như những người khác đã nêu, tối ưu hóa trình biên dịch sẽ thực sự chuyển nối thành một chữ ("ab").

Bạn không bao giờ có thể hoàn toàn dựa vào ngữ nghĩa của chuỗi == của chuỗi, đó là lý do tại sao bạn nên luôn sử dụng equals(..).

Edit: để làm rõ các câu trên:

Với đối tượng == luôn có nghĩa là tài liệu tham khảo được so sánh và nó sẽ luôn luôn trả về true nếu cả hai tài liệu tham khảo đều giống nhau. Tuy nhiên, bạn không thể luôn luôn dựa vào việc tham chiếu cùng một đối tượng (như trong ví dụ của bạn, nơi đơn giản là final hành vi thay đổi hoặc trong các khung như Hibernate, v.v.) - đó là lý do tại sao bạn nên sử dụng equals(...) để thay thế.

Tất nhiên bạn có thể sử dụng == nếu bạn cần bình đẳng vật lý (cùng một đối tượng) thay vì bình đẳng logic (cùng một giá trị).

Một ví dụ khác nơi == sẽ có kết quả khác nhau, mặc dù từ một điểm locical nhìn cả hai nên được đúng:

Integer l1 = 0; 
Integer l2 = 0; 
l1 == l2; //most often true, since Integer objects up to 127 are cached 

Integer l1 = 1000; 
Integer l2 = 1000; 
l1 == l2; //most often false, since those are not cached anymore 

Lưu ý rằng với "thường xuyên nhất" Tôi có nghĩa là điều này có thể thay đổi giữa các phiên bản Java (nếu không phải các JVM khác nhau), mặc dù điều đó không có khả năng xảy ra.

+2

* "Bạn không bao giờ có thể hoàn toàn dựa vào ngữ nghĩa' == 'của chuỗi" * Chắc chắn bạn có thể , giống như bạn có thể với bất kỳ loại ** tham chiếu ** nào khác. '==' sẽ là 'true' nếu tham chiếu trỏ tới cùng một cá thể và' false' nếu chúng không. 'equals' là về cái gì đó hoàn toàn khác. –

+0

@ T.J. ý tôi là: bạn không phải lúc nào cũng biết liệu bạn có nhận được cùng một tham chiếu về một chuỗi hay không, đó là lý do tại sao bạn không thể dựa vào ngữ nghĩa. (Cũng áp dụng cho 'Integer'). – Thomas

4

Các JLS định này trong phần về String Literals:

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ản xuất đầu ra:

true true true true false true 

BTW: OMM (jdk1.6.0_21, Ubuntu), mã trên không compi le cho đến khi tôi làm other.Other.hellopublic và sau đó nó ra:

true true true true true true 

Cập nhật: nope, lỗi của tôi. IDE của tôi tự động được thêm final vào khai báo biến cục bộ. Nếu tôi xóa nội dung đó, tôi nhận được:

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