2013-02-25 25 views
9

Một người nào đó đã đề xuất trong một số chuỗi diễn đàn mà nhiều người và thậm chí cả các nhà phát triển Java có kinh nghiệm sẽ không hiểu được sự an toàn của Mã Java sau đây.Hành vi khó hiểu của == sau khi gửi thư

Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1++ == i2++); 
System.out.println(i1 == i2); 

Là một người quan tâm đến Java, tôi đã đưa ra suy nghĩ của mình và đưa ra kết quả sau.

System.out.println(i1++ == i2++); 
// True, since we first check for equality and increment both variables afterwards. 

System.out.println(i1 == i2); 
// True again, since both variables are already incremented and have the value 128 

Eclipse nói cách khác. Dòng đầu tiên là true và dòng thứ hai là false.

Tôi thực sự sẽ đánh giá cao giải thích.

Câu hỏi thứ hai. Java này có cụ thể hay ví dụ này giữ ví dụ cho các ngôn ngữ dựa trên C?

+0

thử 'i1.equals (i2)' – vikingsteve

+8

http://stackoverflow.com/questions/5117132/integer-wrapper-objects-share-the-same-instances-only-within-the-value-127 –

+0

Điều này câu hỏi là cực kỳ tương tự như một được đăng bởi @DominikKunicki –

Trả lời

14
Integer i1 = 127; 
Integer i2 = 127; 
System.out.println(i1++ == i2++); 
// here i1 and i2 are still 127 as you expected thus true 
System.out.println(i1 == i2); 
// here i1 and i2 are 128 which are equal but not cached 
    (caching range is -128 to 127), 

Trong trường hợp 2 nếu bạn sử dụng equals() nó sẽ trở thành sự thật như == điều hành cho số nguyên chỉ hoạt động cho các giá trị được lưu trữ. như 128 là ra khỏi phạm vi bộ nhớ cache các giá trị trên 128 sẽ không được lưu trữ, do đó youhave sử dụng equals() phương pháp để kiểm tra xem hai trường hợp số nguyên trên 127 là đúng

TEST:

Integer i1 = 126; 
    Integer i2 = 126; 
    System.out.println(i1++ == i2++);// true 
    System.out.println(i1 == i2); //true 



Integer i1 = 126; 
     Integer i2 = 126; 
     System.out.println(i1++ == i2++);// true 
     System.out.println(i1.equals(i2)); //true 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++ == i2++);// false 
     System.out.println(i1==i2); //false 

    Integer i1 = 128; 
     Integer i2 = 128; 
     System.out.println(i1++.equals(i2++));// true 
     System.out.println(i1.equals(i2)); //true 
+4

Để lưu ý, tôi tin rằng phạm vi bộ nhớ đệm là cài đặt JVM cụ thể và không phải là một phần của JLS. Do đó, hành vi này không được đảm bảo để nhất quán giữa các JVM. –

+1

@ChrisKnight Nó không thực hiện cụ thể, vì nó nằm trong đặc điểm kỹ thuật. [Đoạn 5.1.7] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7) nêu rõ: * "Nếu giá trị p được đóng hộp là [...] một số int hoặc ngắn giữa -128 và 127 (bao gồm), sau đó cho 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. "* –

+1

@ Mattias Buelens - Chúng tôi đều đúng.Để làm rõ, -128 đến 127 (bao gồm) được đảm bảo. Tuy nhiên, JVM có thể mở rộng phạm vi lưu trữ này. Văn bản khác trong tham chiếu của bạn: "Ít triển khai bộ nhớ hạn chế hơn, ví dụ: lưu trữ tất cả giá trị char và giá trị ngắn, cũng như giá trị int và dài trong phạm vi từ -32K đến + 32K". –

1

Như giải thích điều này là do Integer caching. Để giải trí, bạn có thể chạy chương trình bằng tùy chọn JVM sau:

-XX:AutoBoxCacheMax=128 

và nó sẽ in đúng hai lần (tùy chọn có sẵn trên máy chủ 7 - không nhất thiết trên các JVM khác).

Lưu ý rằng:

  • đây là JVM cụ thể
  • hành vi sửa đổi là phù hợp với JLS mà nói rằng tất cả các giá trị giữa -128 và 127 phải được lưu trữ mà còn nói rằng giá trị khác có thể được lưu trong bộ nhớ cache.

Bottom line: báo cáo kết quả in thứ hai là undefined trong Java và có thể in ra đúng hay sai tùy thuộc vào việc thực hiện JVM và/hoặc các tùy chọn JVM sử dụng.

+0

Chỉ cần chạy nó với tham số đó - và vẫn còn sai. –

+0

@AleksG Nó hoạt động với phiên bản hotspot 7u11. – assylias

+0

Với OpenJDK trên Linux 64-bit thì không. –

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