原文地址:https://blog.csdn.net/chenliguan/article/details/53888018
1 int與Integer的基本使用對比
(1)Integer是int的包裝類;int是基本數據類型;
(2)Integer變量必須實例化后才能使用;int變量不需要;
(3)Integer實際是對象的引用,指向此new的Integer對象;int是直接存儲數據值 ;
(4)Integer的默認值是null;int的默認值是0。
2 int與Integer的深入對比
(1)由於Integer變量實際上是對一個Integer對象的引用,所以兩個通過new生成的Integer變量永遠是不相等的(因為new生成的是兩個對象,其內存地址不同)。
Integer i = new Integer(100); Integer j = new Integer(100); System.out.print(i == j); //false
(2)Integer變量和int變量比較時,只要兩個變量的值是向等的,則結果為true(因為包裝類Integer和基本數據類型int比較時,java會自動拆包裝為int,然后進行比較,實際上就變為兩個int變量的比較)
Integer i = new Integer(100); int j = 100; System.out.print(i == j); //true
(3)非new生成的Integer變量和new Integer()生成的變量比較時,結果為false。(因為非new生成的Integer變量指向的是java常量池中的對象,而new Integer()生成的變量指向堆中新建的對象,兩者在內存中的地址不同)
Integer i = new Integer(100); Integer j = 100; System.out.print(i == j); //false
(4)對於兩個非new生成的Integer對象,進行比較時,如果兩個變量的值在區間-128到127之間,則比較結果為true,如果兩個變量的值不在此區間,則比較結果為false
Integer i = 100; Integer j = 100; System.out.print(i == j); //true Integer i = 128; Integer j = 128; System.out.print(i == j); //false
對於第4條的原因: java在編譯Integer i = 100 ;時,會翻譯成為Integer i = Integer.valueOf(100)。而java API中對Integer類型的valueOf的定義如下,對於-128到127之間的數,會進行緩存,Integer i = 127時,會將127進行緩存,下次再寫Integer j = 127時,就會直接從緩存中取,就不會new了。
public static Integer valueOf(int i){ assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high){ return IntegerCache.cache[i + (-IntegerCache.low)]; } return new Integer(i); }
3 Java兩種數據類型
3.1 Java兩種數據類型分類
(1)基本數據類型,分為boolean、byte、int、char、long、short、double、float;
(2)引用數據類型 ,分為數組、類、接口。
3.2 Java為每個原始類型提供了封裝類
為了編程的方便還是引入了基本數據類型,但是為了能夠將這些基本數據類型當成對象操作,Java為每 一個基本數據類型都引入了對應的包裝類型(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換。
基本數據類型: boolean,char,byte,short,int,long,float,double 封裝類類型:Boolean,Character,Byte,Short,Integer,Long,Float,Double
4 基本解析
4.1 自動裝箱:將基本數據類型重新轉化為對象
public class Test { public static void main(String[] args) { //聲明一個Integer對象 Integer num = 9; //以上的聲明就是用到了自動的裝箱:解析為:Integer num = new Integer(9); } }
9是屬於基本數據類型的,原則上它是不能直接賦值給一個對象Integer的,但jdk1.5后你就可以進行這樣的聲明。自動將基本數據類型轉化為對應的封裝類型,成為一個對象以后就可以調用對象所聲明的所有的方法。
4.2 自動拆箱:將對象重新轉化為基本數據類型
public class Test { public static void main(String[] args) { //聲明一個Integer對象 Integer num = 9; //進行計算時隱含的有自動拆箱 System.out.print(num--); } }
因為對象時不能直接進行運算的,而是要轉化為基本數據類型后才能進行加減乘除。對比:
/裝箱 Integer num = 10; //拆箱 int num1 = num;
5 深入解析
5.1 情況描述
public class Test { public static void main(String[] args) { //在-128~127 之外的數 Integer num1 = 128; Integer num2 = 128; System.out.println(num1==num2); //false // 在-128~127 之內的數 Integer num3 = 9; Integer num4 = 9; System.out.println(num3==num4); //true } }
解析原因:歸結於java對於Integer與int的自動裝箱與拆箱的設計,是一種模式:叫享元模式(flyweight)。
加大對簡單數字的重利用,Java定義在自動裝箱時對於值從–128到127之間的值,它們被裝箱為Integer對象后,會存在內存中被重用,始終只存在一個對象。
而如果超過了從–128到127之間的值,被裝箱后的Integer對象並不會被重用,即相當於每次裝箱時都新建一個 Integer對象。
5.2 Integer源碼解析
給一個Integer對象賦一個int值的時候,會調用Integer類的靜態方法valueOf,源碼如下:
public static Integer valueOf(String s, int radix) throws NumberFormatException { return Integer.valueOf(parseInt(s,radix)); }
public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); }
IntegerCache是Integer的內部類,源碼如下:
/** * 緩存支持自動裝箱的對象標識語義 * -128和127(含)。 * * 緩存在第一次使用時初始化。 緩存的大小 * 可以由-XX:AutoBoxCacheMax = <size>選項控制。 * 在VM初始化期間,java.lang.Integer.IntegerCache.high屬性 * 可以設置並保存在私有系統屬性中 */ private static class IntegerCache { 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) { 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); } 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() {} }