天天看點

自動拆箱和裝箱(一)

為什麼會需要包裝類型

  我們知道Java是一個面相對象的程式設計語言,基本類型并不具有對象的性質,為了讓基本類型也具有對象的特征,就出現了包裝類型(如我們在使用集合類型Collection時就一定要使用包裝類型而非基本類型),它相當于将基本類型“包裝起來”,使得它具有了對象的性質,并且為其添加了屬性和方法,豐富了基本類型的操作。

  當需要往ArrayList,HashMap中放東西時,像int,double這種基本類型是放不進去的,因為容器都是裝object的,這是就需要這些基本類型的包裝器類了。

Java的基本類型(中繼資料)與對應的包裝類型:

基本類型 基本類型大小 包裝類型
byte 1個位元組 Byte
shot 2個位元組 Short
int 4個位元組 Integer
long 8個位元組 Long
float 4個位元組 Float
double 8個位元組 Double
char 取決于底層儲存的字元 Character
boolean Boolean

包裝類的缺點:

  在 64 位的 Java 虛拟機中,每一個 Java 對象在記憶體中的額外開銷就最少是16 個位元組。以 Integer 類為例,它僅有一個 int 類型的私有字段,占 4 個位元組。是以,每一個 Integer 對象的額外記憶體開銷至少是int的400%

什麼是自動裝箱和拆箱

自動裝箱:将基本的類型資料轉換為對應的包裝包裝類型資料

Integer a = 1;//裝箱

自動拆箱:将包裝類型轉換為基本類型資料

int b = a; //拆箱

自動拆箱和裝箱的實作

下面是很簡單的自動裝箱與自動拆箱的代碼,進過反編譯結果在下圖:

自動拆箱和裝箱(一)

當進行自動裝箱時代用的是valueOf()方法

自動拆箱和裝箱(一)

當進行自動拆箱時,代用的是intValue()方法

自動拆箱和裝箱(一)

IntegerCahe分析

IntegerCache的詳細可以看:https://blog.csdn.net/zx6571269/article/details/82026879 這篇文章是轉載的個人感覺寫的非常好

Integer裡面隻有一個value屬性.

自動拆箱和裝箱(一)

swap主要用于交換兩個Integer對象在棧裡面的資料。

private  static void swap(Integer a,Integer b) throws NoSuchFieldException, IllegalAccessException {
        Field valueField = Integer.class.getDeclaredField("value");
        valueField.setAccessible(true);
        int temp = valueField.getInt(a);
        valueField.setInt(a,b.intValue());
        valueField.setInt(b,temp);
    }
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        Integer a=,b=;
        swap(a,b);
        System.out.println("a=:"+a);
        System.out.println("b=:"+b);

        Integer c=;
        System.out.println("c=:"+c);
        System.out.println("b=:"+b);
    }
           

大家可以猜猜結果:

自動拆箱和裝箱(一)

IntegerCache實作

/**
     * 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.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */
 private static class IntegerCache {
        static final int low = -;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = ;
            //查找JVM,Integer初始化的緩存設定
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, );
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;
            //建立緩存數組
            cache = new Integer[(high - low) + ];
            int j = low;
            for(int k = ; k < cache.length; k++)
                cache[k] = new Integer(j++);

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

        private IntegerCache() {}
    }
           

  IntegerCache是一個靜态的内部類,當,第一次初始化化是,,

int c = 1

反編譯後的

Integer c = Integer.valueOf((int)1);

其中java.lang.Integer.IntegerCache.high的取值範圍,它預設的範圍是[-128,127]之間。在該區間内所有的

Integer.valueOf(int)

函數傳回的對象,是根據int值計算的偏移量,從數組

Integer.IntegerCache.cache

中擷取,對象是同一個,不會建立對象。是以當我們修改了Integer.valueOf(1)的value後,所有

Integer.IntegerCache.cache[ 1 - IntegerCache.low ]

的傳回值都會變更。

包裝類 是否有Cache 範圍
Byte ByteCache [-128,127](固定)
Short ShortCache [-128,127](固定)
int IntegerCache [-128,Integer.MAX_VALUE - (-low) -1]
long LongCache [-128,127](固定)
float
Double
Character CharacterCache [0,127]
Boolean

參考1:https://www.jb51.net/article/129640.htm

參考2:https://www.cnblogs.com/dolphin0520/p/3780005.html

參考3:https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

繼續閱讀