2010-06-04 26 views
64

Tôi đã sử dụng Sonar để làm cho mã của tôi sạch hơn và chỉ ra rằng tôi đang sử dụng new Integer(1) thay vì Integer.valueOf(1). Vì có vẻ như valueOf không khởi tạo một đối tượng mới nên thân thiện với bộ nhớ hơn. Làm cách nào để valueOf không khởi tạo một đối tượng mới? Làm thế nào nó hoạt động? Điều này có đúng với tất cả các số nguyên không?Số nguyên mới và giá trịOf

+13

Lưu ý: nếu bạn sử dụng autoboxing, nó sử dụng Integer. valueOf (int) cho bạn. –

Trả lời

66

Integer.valueOf triển khai bộ nhớ cache cho các giá trị -128 đến +127. Xem đoạn cuối của Đặc tả Ngôn ngữ Java, mục 5.1.7, giải thích các yêu cầu về quyền anh (thường được thực hiện theo các phương thức .valueOf).

http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.7

+0

tôi biết, đó là một nơi nào đó trong unboxing, nhưng tôi có thể tìm thấy phần. thanks – LB40

+1

Phần đó không nói bất cứ điều gì rõ ràng về valueOf. Quyền anh thường được thực hiện dưới dạng giá trịOf, nhưng điều đó không bắt buộc. Ngoài ra, nó cũng được phép lưu trữ các giá trị ngoài phạm vi đó. Đó chỉ là một phạm vi tối thiểu cho quyền anh. –

+21

Chỉ để hoàn thành, cũng lưu ý rằng trên máy ảo Sun, giá trị tối đa của bộ nhớ cache là người dùng cấu hình bằng cách sử dụng '-XX: AutoBoxCacheMax = ...' –

26

Từ JavaDoc:

public static Integer valueOf (int i) Trả về một ví dụ Integer đại diện cho các giá trị int quy định. Nếu một trường hợp Integer mới không được yêu cầu, phương pháp này thường được sử dụng tùy thuộc vào hàm tạo Integer (int), vì phương thức này có khả năng mang lại hiệu suất thời gian và không gian tốt hơn đáng kể bằng cách lưu các giá trị được yêu cầu.

ValueOf được sử dụng chung cho hộp tự động và do đó (khi được sử dụng cho hộp số tự động) lưu trữ ít nhất các giá trị từ -128 đến 127 để tuân theo đặc tả autoboxing.

Đây là triển khai valueOf cho Sun JVM 1.5.? Hãy xem toàn bộ lớp để xem bộ đệm được khởi tạo như thế nào.

public static Integer valueOf(int i) { 
    final int offset = 128; 
    if (i >= -128 && i <= 127) { // must cache 
     return IntegerCache.cache[i + offset]; 
    } 
    return new Integer(i); 
} 
2

họ đang thúc đẩy bạn sử dụng valueOf() thay vì new Integer() nên phương pháp valueOf() nào đó cho bạn, và lưu trữ các giá trị trong trường hợp bạn muốn nhận được cùng một số lần nữa trong tương lai. Trong trường hợp đó, phương pháp sẽ không instatiate Integer mới, nhưng sẽ cung cấp cho bạn một trong những bộ nhớ đệm, những gì sẽ làm cho 'sáng tạo' mới Integer nhanh hơn rất nhiều và bộ nhớ thân thiện quá trình ..

Bằng cách này bạn có thể gây ra cho mình rất nhiều vấn đề nếu bạn là lập trình viên java chưa từng trải nghiệm vì bạn sẽ kết luận rằng Integer.valueOf(342)==Integer.valueOf(342), bởi vì bạn có thể (hoặc có thể không) có cùng một con trỏ cho hai Số nguyên, và có thể bạn sẽ thực hành nó theo cách, giả sử bạn đã học trong C#, để sẽ hiển thị cho bạn các lỗi theo thời gian và bạn sẽ không biết cách & nơi những người này đến từ ...

2

Từ mã nguồn java.lang.Integer. Bộ nhớ cache số nguyên được cấu hình. Để cấu hình kích thước bộ đệm Integer khác với Sun, chúng ta cần sử dụng thuộc tính System java.lang.Integer.IntegerCache.high theo mã nguồn.

/** 
* Cache to support the object identity semantics of autoboxing for values between 
* -128 and 127 (inclusive) as required by JLS. 
* 
* The cache is initialized on first usage. During VM initialization the 
* getAndRemoveCacheProperties method may be used to get and remove any system 
* properites that configure the cache size. At this time, the size of the 
* cache may be controlled by the vm option -XX:AutoBoxCacheMax=<size>. 
*/ 

// value of java.lang.Integer.IntegerCache.high property (obtained during VM init) 
private static String integerCacheHighPropValue; 

static void getAndRemoveCacheProperties() { 
    if (!sun.misc.VM.isBooted()) { 
     Properties props = System.getProperties(); 
     integerCacheHighPropValue = 
      (String)props.remove("java.lang.Integer.IntegerCache.high"); 
     if (integerCacheHighPropValue != null) 
      System.setProperties(props); // remove from system props 
    } 
} 

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() {} 
} 

Từ java.lang.Short, java.lang.Byte và java.lang.Long tạo ra một bộ nhớ cache của 127 đến -128

private static class LongCache { 
    private LongCache() { 
    } 

    static final Long cache[] = new Long[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Long(i - 128); 
    } 
} 

private static class ShortCache { 
    private ShortCache() { 
    } 

    static final Short cache[] = new Short[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Short((short) (i - 128)); 
    } 
} 

private static class ByteCache { 
    private ByteCache() { 
    } 

    static final Byte cache[] = new Byte[-(-128) + 127 + 1]; 

    static { 
     for (int i = 0; i < cache.length; i++) 
      cache[i] = new Byte((byte) (i - 128)); 
    } 
} 
Các vấn đề liên quan