2013-02-22 18 views
23

Tại sao số nguyên Toán tử "=" không hoạt động đối với 128 và sau giá trị Integer? Ai đó có thể giải thích tình huống này?Tại sao toán tử bằng nhau hoạt động với giá trị Integer cho đến 128 số?

Đây là môi trường Java của tôi: phiên bản java "1.6.0_37"

Java (TM) SE Runtime Environment (xây dựng 1.6.0_37-b06)

Java HotSpot (TM) 64 server Bit VM (xây dựng 20.12-b01, chế độ hỗn hợp)

Sample Code:

Integer a; 
    Integer b; 
    a = 129; 
    b = 129; 

    for (int i = 0; i < 200; i++) { 
     a = i; 
     b = i; 

     if (a != b) { 
      System.out.println("Value:"+ i + " - Different values"); 
     } else { 
      System.out.println("Value"+ i + " Same values"); 
     } 
    } 

Một số phần của giao diện điều khiển đầu ra:

Value:124 - Same values 
Value:125 - Same values 
Value:126 - Same values 
Value:127 - Same values 
Value:128 - Different values 
Value:129 - Different values 
Value:130 - Different values 
Value:131 - Different values 
Value:132 - Different values 

Cảm ơn!

+0

từ -128 đến 127 –

+0

'=' là toán tử gán và bạn không sử dụng nó trong mã ví dụ thực tế của mình; bạn có nghĩa là '=='? – geoffspear

Trả lời

19

Kiểm tra the source code of Integer. Bạn có thể thấy bộ nhớ đệm của các giá trị ở đó.

Việc lưu vào bộ nhớ cache chỉ xảy ra nếu bạn sử dụng Integer.valueOf(int), không phải nếu bạn sử dụng new Integer(int). Hộp số tự động được bạn sử dụng Integer.valueOf

Theo số JLS, bạn luôn có thể nhận được các đối tượng Integer giống nhau sau khi autoboxing và trên một số triển khai, bạn có thể nhận được các đối tượng giống hệt nhau ngay cả đối với các giá trị cao hơn.

Thực ra trong Java 7 (và tôi nghĩ trong phiên bản mới hơn của Java 6), lớp implementation của lớp IntegerCache đã thay đổi và giới hạn trên không còn được mã hóa cứng nữa, nhưng có thể cấu hình được thông qua thuộc tính "java.lang. Integer.IntegerCache.high ", vì vậy nếu bạn chạy chương trình của mình với tham số VM -Djava.lang.Integer.IntegerCache.high=1000, bạn sẽ nhận được" Các giá trị giống nhau "cho tất cả các giá trị.

Nhưng JLS vẫn đảm bảo nó chỉ cho đến khi 127:

Lý tưởng nhất, đấm bốc một định nguyên thủy giá trị p, sẽ luôn mang lại một tham chiếu giống hệt 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ị được đó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 tất cả các ký tự và quần short, cũng như các số nguyên và độ dài trong phạm vi -32K - + 32K.

+0

+1 Thật tuyệt nếu bạn liên kết mã nguồn với câu trả lời của bạn :) – PermGenError

6

Theo Java Ngôn ngữ Thông số kỹ thuật:

Nếu p giá trị được đóng hộp là đúng, sai, một byte, một char trong khoảng \ u0000 để \ u007f, hoặc một int hoặc số ngắn giữa - 128 và 127, 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ó là luôn luôn là trường hợp r1 == r2.

JLS Boxing Conversions

Refer to this article for more information on int caching

+5

Câu trả lời này là sai, nó không phải làm gì với các hotspot jvm, bộ nhớ đệm được thực hiện trong mã nguồn của Integer, – lbalazscs

+1

@lbalazscs theo như tôi biết các giá trị được lưu trữ là phụ thuộc jvm. Tôi nghĩ rằng bộ nhớ đệm này được xác định trong đặc tả ngôn ngữ java, nhưng các giá trị được lưu trữ không được chỉ định. Đây là lý do tại sao tôi đề cập đến hotspot jvm. Điều này có đúng không? –

+3

Nó không chính xác. Tại sao bạn không có một cái nhìn vào mã nguồn của 'java.lang.Integer', ví dụ. –

2

Sử dụng .equals() thay vì ==.

Giá trị số nguyên chỉ được lưu trong bộ nhớ cache cho các số từ -127 đến 128, vì chúng được sử dụng thường xuyên nhất.

if (a.equals(b)) { ... } 
6

Integer là lớp bao bọc cho int.

Integer != Integer so sánh tham chiếu đối tượng thực tế, trong đó int != int sẽ so sánh các giá trị.

Như đã nêu, các giá trị -128 đến 127 được lưu trong bộ nhớ cache, vì vậy các đối tượng giống nhau được trả về cho các giá trị đó.

Nếu ngoài phạm vi đó, các đối tượng riêng biệt sẽ được tạo để tham chiếu sẽ khác nhau.

Để khắc phục nó:

  • Hãy loại int hay
  • Cast loại để int hay
  • Sử dụng .equals()
3

Đối tượng Integer có một cơ chế bộ nhớ cache nội bộ:

private static class IntegerCache { 
    static final int high; 
    static final Integer cache[]; 

    static { 
     final int low = -128; 

     // high value may be configured by property 
     int h = 127; 
     if (integerCacheHighPropValue != null) { 
      // Use Long.decode here to avoid invoking methods that 
      // require Integer's autoboxing cache to be initialized 
      int i = Long.decode(integerCacheHighPropValue).intValue(); 
      i = Math.max(i, 127); 
      // Maximum array size is Integer.MAX_VALUE 
      h = Math.min(i, Integer.MAX_VALUE - -low); 
     } 
     high = h; 

     cache = new Integer[(high - low) + 1]; 
     int j = low; 
     for(int k = 0; k < cache.length; k++) 
      cache[k] = new Integer(j++); 
    } 

    private IntegerCache() {} 
} 

Xem thêm phương pháp valueOf:

public static Integer valueOf(int i) { 
    if(i >= -128 && i <= IntegerCache.high) 
     return IntegerCache.cache[i + 128]; 
    else 
     return new Integer(i); 
} 

Đây là lý do tại sao bạn nên sử dụng valueOf thay vì new Integer. Tự động hóa sử dụng bộ nhớ cache này.

Cũng xem bài này: https://effective-java.com/2010/01/java-performance-tuning-with-maximizing-integer-valueofint/

Sử dụng == không phải là một ý tưởng tốt, sử dụng tương đương để so sánh các giá trị.

1

Tùy thuộc vào cách bạn nhận được Integer trường hợp của bạn, nó có thể không làm việc cho bất kỳ giá trị:

System.out.println(new Integer(1) == new Integer(1)); 

in

false 

toán hạng này là vì các nhà điều hành == áp dụng để tham khảo, đánh máy đã không có gì để làm với giá trị mà các toán hạng đó đại diện.

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