2011-06-15 25 views
7

tôi đang làm việc trên chương trình java cơ bản và tôi đã tìm thấy điều thú vị mà tôi đang chia sẻ với bạn. foo() cho đầu ra (s == s1) = false và thanh cho (s == s1) = true.Tại sao tôi nhận được kết quả khác khi so sánh chuỗi sau khi sử dụng nối khác nhau trong Java?

Tôi muốn biết tại sao điều này xảy ra.

public class StringTest 
{ 
    public static void main(String[] args){ 
    foo(); 
    bar(); 
    } 
    public static void foo(){ 
    String s = "str4"; 
    String s1 = "str" + s.length(); 
    System.out.println("(s==s1) = " + (s1==s)); 
    } 
    public static void bar(){ 
    String s = "str4"; 
    String s1 = "str" + "4"; 
    System.out.println("(s==s1) = " + (s1==s)); 
} 
} 
+1

nếu bạn đang cố gắng so sánh các giá trị Chuỗi, bạn nên thực hiện ['equals'] (http: // downlo ad.oracle.com/javase/6/docs/api/java/lang/String.html#equals(java.lang.Object)) – asgs

+0

Lưu ý: Thẻ HTML không hoạt động ở đây để định dạng mã. – Jesper

+0

Tôi tự hỏi làm thế nào con người lỗi ra có liên quan đến vấn đề này ...;) – Nix

Trả lời

16

Trong trường hợp thứ hai, trình biên dịch tối ưu hóa chuỗi nối. Vì điều này có thể được thực hiện tại thời gian biên dịch, cả hai tham chiếu cùng một đối tượng chuỗi không đổi.

Trong trường hợp trước, không thể tối ưu hóa cuộc gọi length() trong thời gian biên dịch. Khi chạy, một đối tượng chuỗi mới được tạo, không giống với chuỗi ký tự (nhưng bằng với nó)

+0

+1 để giải thích * tại sao * đó là cách nó là – Sorrow

+0

Thanx buddy .. !! – Chakravyooh

+0

nhưng nếu tôi sẽ thay đổi giá trị của s1 trong thanh() sau khi ompersion .. ?? – Chakravyooh

3

Việc ghép chuỗi trong bar() có thể được thực hiện tại thời gian biên dịch, vì nó là biểu thức không có gì ngoài hằng số thời gian biên dịch. Mặc dù chiều dài của chuỗi s rõ ràng là được biết đến lúc biên dịch, trình biên dịch không biết rằng length() trả về giá trị đã biết đó, vì vậy nó sẽ không được sử dụng như một hằng số.

+0

+1, nhưng không ai đã đề cập bằng cách sử dụng '.equals()' để so sánh chuỗi bình đẳng? – Mikaveli

+1

@Mikaveli: Tôi tin @Chakravyooh biết về điều đó, nhưng nó không liên quan đến câu hỏi. Nếu bạn sử dụng 'equals()', thì hành vi thú vị ở đây chỉ đơn giản là ẩn, và đâu là niềm vui trong đó? –

0

Nó có thể liên quan đến thực tế là foo() có thể tạo một thể hiện String mới trong s. length() (. toString()), khi thanh() chỉ nối một hằng số. Tôi không biết nitty gritty của nó, nhưng ruột của tôi nói với tôi nó theo hướng đó

2

Khi bạn viết một dòng mã như thế này:

String s1 = "str" + "4"; 

sau đó trình biên dịch là đủ thông minh để tối ưu hóa này đến:

String s1 = "str4"; 

Chuỗi ký tự trong Java được quản lý trong một nhóm chuỗi. Khi bạn có hai chuỗi ký tự có nội dung giống nhau (chẳng hạn như ss1 trong ví dụ thứ hai), thì chỉ một đối tượng String sẽ được tạo sẽ được chia sẻ bởi hai biến.

Toán tử == trong kiểm tra Java nếu hai biến tham chiếu đến cùng một đối tượng. Vì chỉ có một đối tượng String trong ví dụ thứ hai, s == s1 sẽ là true.

0

Nếu tôi cần đoán tôi sẽ nói trình biên dịch java thực hiện một số tối ưu hóa trên thanh(). Tại compiletime, rõ ràng là "str" ​​+ "4" có thể được thay thế bằng "str4" (vì các chuỗi là các đối tượng bất biến) thực sự là đối tượng rất giống với "str4" -String được sử dụng để khởi tạo s.

Trong vòng foo(), tối ưu hóa không phải là tiến triển về phía trước. Nói chung giá trị s1-biến không thể được dự đoán rất dễ dàng (thực sự ví dụ này là khá streight về phía trước). Vì vậy, trình biên dịch java sẽ tạo ra hai biến khác nhau cho s và s1.

Toán tử "==" không so sánh giá trị của chuỗi! Nó kiểm tra xem đây là những đối tượng tương tự. Để so sánh các giá trị của các Chuỗi sử dụng phương thức "bằng" như sau:

String s = "str4"; 
String s1 = "str" + s.length(); 
System.out.println("(s==s1) = " + (s1.equals(s2)); 
0

Bạn nên thử chơi với phương thức thực tập của lớp Chuỗi. Java giữ một cái gì đó giống như từ điển, nơi tất cả các chuỗi khác nhau được lưu trữ. Khi bạn tạo một đối tượng chuỗi có thể được đánh giá tại thời gian biên dịch, Java sẽ tìm kiếm nó trong từ điển của nó.Nếu nó tìm thấy chuỗi, nó chỉ lưu trữ một tham chiếu đến chuỗi này (mà thực sự được trả về bởi phương thức thực tập).

Bạn nên lưu ý rằng: "str4" == ("str" + "str4".length()) trả về false, nhưng "str4" == ("str" + "str4".length()).intern() trả về true, bởi vì "trình bao bọc" duy nhất là một đối tượng khác.

2
  • String s1 = "str" + s.length();
  • String s1 = "str" + "4";

Trong trường hợp đầu tiên s.length() sẽ trả về một giá trị kiểu int , Trong trường hợp thứ hai loại là Chuỗi Mặc dù con số này 4 trong cả hai trường hợp nhưng các loại không giống nhau :)

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