2012-04-03 50 views
24

Walk với tôi ..So sánh giá trị Integer trong Java, hành vi kỳ lạ

Integer x = 23; 
Integer y = 23; 

if (x == y) 
    System.out.println("what else");  // All is well as expected 
else 
    System.out.println("..."); 

Trong khi

Integer x = someObject.getIndex(); 
Integer y = someOtherObject.getSomeOtherIndex(); 

if (x == y) 
    System.out.println("what else"); 
else 
    System.out.println("...");  // Prints this 

Hmm ... Tôi cố gắng đúc để int

int x = someObject.getIndex(); 
int y = someOtherObject.getSomeOtherIndex() 

if (x == y)  
    System.out.println("what else"); // works fine 
else 
    System.out.println("..."); 

Họ có cả hai Số nguyên?

System.out.println(x.getClass().getName());    // java.lang.Integer 
System.out.println(y.getClass().getName());    // java.lang.Integer 
System.out.println(someObject.getIndex());    // java.lang.Integer 
System.out.println(someOtherObject.getSomeOtherIndex()); // java.lang.Integer 

Các bạn nghĩ sao? Điều gì sẽ giải thích một cái gì đó như thế này?

+0

thể trùng lặp của [Làm thế nào = điều hành và == nhà điều hành các công trình trong Java ?] (http://stackoverflow.com/questions/9824053/how-operator-and-operator-works-in-java) – assylias

+0

'getIndex();' và 'getSomeOtherIndex()' làm gì? –

+0

Có thể trùng lặp [Tại sao 128 == 128 trả về false nhưng 127 == 127 trả về true khi chuyển đổi thành Trình bao bọc Integer?] (Https://stackoverflow.com/questions/1700081/why-does-128-128-return- false-but-127-127-return-true-when-conversion-to-integ) – Tom

Trả lời

42

Bạn đang so sánh các giá trị Integer, là các tham chiếu. Bạn đang đến với những tài liệu tham khảo thông qua autoboxing. Đối với một số giá trị (được bảo đảm cho -128 đến 127), JRE duy trì bộ nhớ cache của các đối tượng Integer. Đối với các giá trị cao hơn, nó không. Từ section 5.1.7 of the JLS:

Nếu p giá trị được đóng hộp là đúng, sai, một byte, hoặc một char trong khoảng \ u0000 để \ u007f, hoặc một int hoặc số ngắn giữa -128 và 127 (bao gồm), sau đó để r1 và r2 là kết quả của bất kỳ chuyển đổi đấm bốc nào của p. Nó luôn luôn là trường hợp r1 == r2.

Lý tưởng nhất, hãy đấm một giá trị nguyên thủy p, sẽ luôn mang lại một tham chiếu giống nhau. Trong thực tế, điều này có thể không khả thi khi sử dụng các kỹ thuật triển khai hiện có. Các quy tắc trên là một sự thỏa hiệp thực dụng. Điều khoản cuối cùng ở trên yêu cầu các giá trị chung nhất định luôn được đóng hộp thành các đối tượng không thể phân biệt được. Việc triển khai có thể lưu vào bộ nhớ cache, lười biếng hoặc háo hức. Đối với các giá trị khác, công thức này không cho phép bất kỳ giả định nào về danh tính của các giá trị đóng hộp trên phần của lập trình viên. Điều này sẽ cho phép (nhưng không yêu cầu) chia sẻ một số hoặc tất cả các tài liệu tham khảo này.

Điều này đảm bảo rằng trong hầu hết các trường hợp phổ biến, hành vi sẽ là hành vi mong muốn, không áp đặt hình phạt hiệu suất quá mức, đặc biệt là trên các thiết bị nhỏ. Ví dụ, ít triển khai bộ nhớ hạn chế hơn, có thể lưu trữ tất cả các giá trị char và ngắn, cũng như các giá trị int và long trong phạm vi từ -32K đến + 32K.

Đạo đức: không so sánh Integer tham chiếu khi bạn quan tâm đến giá trị int cơ bản. Sử dụng .equals() hoặc nhận các giá trị int trước tiên.

+2

@JAM: Có, hoặc là cast thành 'int', gọi' intValue() 'và so sánh kết quả, hoặc gọi' equals() '. –

+1

Ok tuyệt vời; Cảm ơn bạn Jon! – JAM

1

Âm thanh như thứ gì đó sôi nổi với tự động đấm bốc khi bạn sử dụng == trên hai số nguyên.

Tôi cho rằng nó hoạt động tốt khi sử dụng Integer nếu bạn sử dụng phương pháp equals()? Điều đó sẽ do tôi đoán anyway.

Bạn hiện không sử dụng java 1.4 hoặc gì đó?

+0

Các câu trả lời khác cho biết chính xác lý do tại sao điều này xảy ra: JVM lưu trữ các giá trị nhỏ của Số nguyên. Vì vậy, khi tôi so sánh (Integer mới (12) == Integer mới (12)) [yields true] JVM trả về đối tượng được lưu trữ SAME cho cả hai mặt của giá trị đó 12. Vì vậy, thực sự các đối tượng là như nhau. Đối với các giá trị lớn, các đối tượng mới độc lập được tạo và điều này không xảy ra. – ingyhere

13

Để so sánh các số nguyên một cách chính xác, bạn cần sử dụng .equals() hoặc so sánh các giá trị nguyên thủy của chúng bằng cách truyền tới int hoặc gọi intValue() trên chúng.

Sử dụng == kiểm tra xem hai số nguyên là cùng Object, không phải là liệu chúng chứa các cùng giá trị số.

Integer a = new Integer(1); 
    Integer b = new Integer(1); 

    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false 

Sửa để minh họa điểm Jon từ JLS về autoboxing:

Integer a = 1; 
    Integer b = 1; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //true 

so:

Integer a = 128; 
    Integer b = 128; 
    System.out.println(a.equals(b));     //true 
    System.out.println((int)a == (int)b);    //true 
    System.out.println(a.intValue() == b.intValue()); //true 
    System.out.println(a == b);      //false