自動裝箱和自動拆箱,對象包裝類型的緩存機制

對象包裝器

將基本數據類型包裝在對象中,通過定義屬性和方法來豐富數據類型的操作,這樣的類稱作對象包裝器類.java中的對象包裝器類有 Byte,Short,Integer,Long,Float,Double,Boolean,Character,Void.

特點:

  1. 對象包裝器類是不可變的,因爲它包裝的基本類型值是final修飾的
  2. 對象包裝器類是final修飾的,所以不能擴展它

java自動拆箱和自動裝箱是jdk1.5之後引進的,是一種編譯現象,編譯器在生成字節碼的時候,會插入必要的方法調用.

自動裝箱:當一個int類型的值賦值給Interget變量時,int類型會被包裝成一個Integer類型的對象

自動拆箱:當一個Integer類型的對象賦值給int時,Integer類的對象會自動的拆箱變爲一個int值;

自動裝箱和拆箱在算術表達式中比較頻繁,如下

 

通過反編譯工具可以看出

自動裝箱時調用的是 public static Integer valueOf(int i)方法

自動拆箱時調用的是 public static intValue()方法

對象包裝器類的相關類圖

Number源碼分析

抽象類Number是BigDecimal,BigInteger,Byte,Double,Float,Integer,Long和Short類的超類.Number的子類必須提供將表示的數值轉換爲byte,double,float,int,long和short的方法

public abstract class Number implements Serializable{
	private static final long serialVersionUID = -8742448824652078965L; 
	
	
	/**
	 * 以byte形式返回指定的數值,涉及到舍入或取整
	 * @return 轉換爲byte類型後該對象表示的值
	 */
	public byte byteValue() {
		return (byte)intValue();
	}
	
	/**
	 * 以short形式返回指定的數值,涉及到舍入或取整
	 * @return 轉換爲short類型後該對象表示的值
	 */
	public short shortValue(){
		return (short)intValue();
	}
	
	/**
	 * 以int形式返回指定的數值,涉及到舍入或取整
	 * @return 轉換爲int類型後該對象表示的值
	 */
	public abstract int intValue();

	/**
	 * 以long形式返回指定的數值,涉及到舍入或取整
	 * @return 轉換爲long類型後該對象表示的值
	 */
	public abstract long longValue();
	
	/**
	 * 以double形式返回指定的數值,涉及到舍入
	 * @return 轉換爲long類型後該對象表示的值
	 */
	public abstract double doubleValue();
	
	
	/**
	 * 以float形式返回指定的數值,涉及到舍入
	 * @return 轉換爲float類型後該對象表示的值
	 */
	public abstract float floatValue();
	
}

 

 

Comparable接口

此接口強行對實現它的每個類的對象進行整體排序,這種排序被稱爲類的自然排序
類的compareTo方法被稱爲它的自然比較方法
實現此接口的對象列表(和數組)可以通過Collections.sort(和Arrays.sort)進行自動排序,實現此接口的對象可以用作
有序映射中的鍵或有序集合中的元素,無需指定比較器


public interface Comparable<T>{
	public int compareTo(T o);
}

Serializable接口(是個標記接口)

類通過實現java.io.Serializable接口來啓用其序列化功能,未實現此接口對的類將無法使其任何狀態序列化或反序列化.
可序列化的所有子類型本身都是可序列化的.
要允許不可序列化類的子類型序列化,可以假定該子類型負責保存和恢復超類型的public,protected和(如果可訪問)包字
段的狀態的責任.子類型可以承擔此責任,只有當它擴展的類具有可訪問的無參構造器來初始化類的狀態時,纔可以假定
子類型有此職責,如果不是這種情況,則聲明一個類可序列化類時錯誤的
 如果可序列化類未顯示聲明serialVersionID,則序列化運行時將基於該類的各個方面計算該類的默認serialVersionUID值

public interface Serializable {
}

 Integer,Short,Byte,Character,Long的緩存

 Integer,Short,Byte,Character,Long等使用靜態內部類提供了緩存機制用於將常用的數據[-128,127]對象存儲.提高內存的利用率和效率,因此當自動裝箱時,相同的int值對應的包裝對象指向同一個引用,只有當int值不在緩存中時,纔會創建新的對象.其中Integer的包裝類型可以通過修改JVM參數來指定緩存的上限.

public class Integer extends Number{
    private final int value;

    private static class IntegerCache{
        static final low = -128;        //緩存的默認下限
        static final high;              //緩存的默認上限
        static final Integer[] cache;   //保存緩存的Integer對象

        static{
            int h = 127;        //設置默認的緩存上限
            
            // 獲取jvm關於java.lang.Integer.IntegerCache.high的設置
            String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 

            if(integerCacheHighPropValue != null){
                try{
                    // 將integerCacheHighPropValue解析爲int,如果不能解析,則拋出 NumberFormatException 異常,默認不對這個異常做處理
                    int i = parseInt(integerCacheHighPropValue);
                    /* 查看設置值是否大於默認值,如果設置值未大於默認值,則繼續使用默認上限127,即設置IntegerCache.high的值無效,此時緩存數組
                       的大小爲 127 - (IntegerCahe.low)+1=256(加1是因爲1~127,-1~127中沒有包括0)
                    */ 
                    i = Math.max(i,127);
                    /**
                        查看此時的上限值是否大於Integer.MAX_VALUE-(-low)-1(
                            爲什麼是這個值呢?
                                因爲數組的大小最大隻能取到MAX_VALUE,默認緩存下限是low=-128,所以要減去
                                -128~-1和0所佔的數組空間.
                        )
                        如果大於,則設置緩存的上限爲Integer.MAX_VALUE,即設置參數不起作用
                     */
                    h = Math.min(i,Integer.MAX_VALUE-(-low)-1);     
                }catch(NumberFormatException nfe){

                }
            }

            high = h;       //獲得最終的緩存上限
            // 創建緩存數組並循環賦值
            cache = new Integer[high-low+1];
            int j = low;
            for(int k = 0;k<cache.length;k++){
                cache[k] = new Integer(j++);
            }
            assert Integer.high >= 127;
        }
    }

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

    public static intValue(){
        return value;
    }
  
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章