1. 程式人生 > >資料型別之Integer與int

資料型別之Integer與int

資料型別之Integer與int

Java入門 

基本資料型別

眾所周知,Java是面向物件的語言,一切皆物件。但是為了相容人類根深蒂固的資料處理習慣,加快常規資料的處理速度,提供了9種基本資料型別,他們都不具備物件的特性,沒有屬性和行為。Java的9種基本資料型別包括 boolean、byte、char、short、int、long、double和refvar。前8種資料型別表示生活中的真假、字元、整數和小數,最後一種refvar是面向物件世界中的引用變數,也叫引用控制代碼。此處認為它也是一種基本資料型別。


前8種都有其對應的包裝資料型別,除了char的對應包裝類名為 Character, int為 Integer外,其它所有對應的包裝類名就是把首字母大寫即可。
下面列出了這8種基本資料型別的空間佔用大小(bit)及對應的包裝類等資訊。

  • boolean/1/Boolean
  • byte/8/Byte
  • char/16/Character
  • short/16/Short
  • int/32/Integer
  • float/32/Float
  • long/64/Long
  • double/64/Double

包裝型別

前8種基本資料型別都有相應的包裝類,因為Java的設計理念是一切皆是物件,在很多情況下,需要以物件的形式操作,比如hashCode()獲取雜湊值,或者getClass獲取類等。包裝類的存在解決了基本資料型別無法做到的事情:泛型型別引數、序列化、型別轉換、高頻區間資料快取。
重點要說的就是最後一項:快取池

快取池

事實上除了Float和Double外,其他包裝型別都會快取。接下來我以介紹Integer的方式來講解快取。
先看一段程式碼

new Integer(123);
Integer.valueOf(123);

new Integer(123) 與 Integer.valueOf(123) 的區別在於:

  • new Integer(123) 每次都會新建一個物件
  • Integer.valueOf(123) 會使用快取池中的物件,多次呼叫會取得同一個物件的引用。

valueOf() 方法的原始碼。

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

如上原始碼,賦值資料i在快取區間內直接返回快取池中的Integer物件,否則就會new一個物件。
因此比較時會出現如下問題:

public class TestIntegerCache {
    public static void main(String[] args) {
        Integer i1 = 100;
        Integer i2 = 100;
        System.out.println(i1 == i2);
        //true

        Integer i3 = 500;
        Integer i4 = 500;
        System.out.println(i3 == i4);
        //false
        System.out.println(i3.equals(i4));
        //true
    }
}

所以推薦所有包裝型別物件之間的比較,全部使用equals方法。

在 Java 8 中,Integer 快取池的大小預設為 -128~127。

static final int low = -128;
static final int high;
static final Integer cache[];

static {
    // high value may be configured by property
    int h = 127;
    String integerCacheHighPropValue =
        sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
    if (integerCacheHighPropValue != null) {
        try {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        } catch( NumberFormatException nfe) {
            // If the property cannot be parsed into an int, ignore it.
        }
    }
    high = h;

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

    // range [-128, 127] must be interned (JLS7 5.1.7)
    assert IntegerCache.high >= 127;
}

基本型別對應的緩衝池如下:

  • boolean values true and false
  • all byte values
  • short values between -128 and 127
  • int values between -128 and 127
  • char in the range \u0000 to \u007F

相關參考:
StackOverflow : Differences between new Integer(123), Integer.valueOf(123) and just 123