淺談 Integer 類


  突然發現自己對Integer i = 10;這種語法不太明白,於是乎有了這篇文章,那么在講解 Integer 之前,我們先看下面這段代碼:

public static void main(String[] args) {
	Integer i = 10;
    Integer j = 10;
    System.out.println(i == j);
     
    Integer a = 128;
    Integer b = 128;
    System.out.println(a == b);
    
    int k = 10;
    System.out.println(k == i);
    int kk = 128;
    System.out.println(kk == a);
     
    Integer m = new Integer(10);
    Integer n = new Integer(10);
    System.out.println(m == n);
}

  大家可以先思考一下結果是什么?

  答案是:

  

  至於為什么是這個結果,下面我們來一一介紹。

1、Integer 類簡介

  首先我們大致看一下Integer是什么,Integer 類在JDK1.0的時候就有了,它是一個類,是 int 基本數據類型的封裝類。

  

  基本API如下:

  

  

  

  

  

  圖片引用:http://blog.csdn.net/litong09282039/article/details/46309541

2、Integer 類和 int 的區別

  ①、Integer 是 int 包裝類,int 是八大基本數據類型之一(byte,char,short,int,long,float,double,boolean)

  ②、Integer 是類,默認值為null,int是基本數據類型,默認值為0;

  ③、Integer 表示的是對象,用一個引用指向這個對象,而int是基本數據類型,直接存儲數值。

3、Integer 的自動拆箱和裝箱

  自動拆箱和自動裝箱是 JDK1.5 以后才有的功能,也就是java當中眾多的語法糖之一,它的執行是在編譯期,會根據代碼的語法,在生成class文件的時候,決定是否進行拆箱和裝箱動作。

  ①、自動裝箱

  一般我們創建一個類的時候是通過new關鍵字,比如:

Object obj = new Object();

  但是對於 Integer 類,我們卻可以這樣:

Integer a = 128;

  為什么可以這樣,通過反編譯工具,我們可以看到,生成的class文件是:

Integer a = Integer.valueOf(128);

  這就是基本數據類型的自動裝箱,128是基本數據類型,然后被解析成Integer類。

  注意:自動裝箱規范要求 byte<= 127、char<=127、-128<=short <=127、-128<=int <=127都被包裝到固定的對象中(緩存)。

  ②、自動拆箱

  我們將 Integer 類表示的數據賦值給基本數據類型int,就執行了自動拆箱。

Integer a = new Integer(128);
int m = a;

  反編譯生成的class文件:

Integer a = new Integer(128);
int m = a.intValue();

  簡單來講:自動裝箱就是Integer.valueOf(int i);自動拆箱就是 i.intValue();

4、回顧開頭的問題

public static void main(String[] args) {
	Integer i = 10;
    Integer j = 10;
    System.out.println(i == j);
     
    Integer a = 128;
    Integer b = 128;
    System.out.println(a == b);
    
    int k = 10;
    System.out.println(k == i);
    int kk = 128;
    System.out.println(kk == a);
     
    Integer m = new Integer(10);
    Integer n = new Integer(10);
    System.out.println(m == n);
}

  我們使用反編譯工具Jad,得到的代碼如下:

	public static void main(String args[])
	{
		Integer i = Integer.valueOf(10);
		Integer j = Integer.valueOf(10);
		System.out.println(i == j);
		Integer a = Integer.valueOf(128);
		Integer b = Integer.valueOf(128);
		System.out.println(a == b);
		int k = 10;
		System.out.println(k == i.intValue());
		int kk = 128;
		System.out.println(kk == a.intValue());
		Integer m = new Integer(10);
		Integer n = new Integer(10);
		System.out.println(m == n);
	}

  打印結果為:

  

  首先,直接聲明Integer i = 10,會自動裝箱變為Integer i = Integer.valueOf(10);Integer i 會自動拆箱為 i.intValue()。

  ①、第一個打印結果為 true

  對於 i == j ,我們知道這是兩個Integer類,他們比較應該是用equals,這里用==比較的是地址,那么結果肯定為false,但是實際上結果為true,這是為什么?

  我們進入到Integer 類的valueOf()方法:

  

  分析源碼我們可以知道在 i >= -128 並且 i <= 127 的時候,第一次聲明會將 i 的值放入緩存中,第二次直接取緩存里面的數據,而不是重新創建一個Ingeter 對象。那么第一個打印結果因為 i = 10 在緩存表示范圍內,所以為 true。

  ②、第二個打印結果為 false

  從上面的分析我們知道,128是不在-128到127之間的,所以第一次創建對象的時候沒有緩存,第二次創建了一個新的Integer對象。故打印結果為false

  ③、第三個打印結果為 true

  Integer 的自動拆箱功能,也就是比較兩個基本數據類型,結果當然為true

  ④、第四個打印結果為 true

  解釋和第三個一樣。int和integer(無論new否)比,都為true,因為會把Integer自動拆箱為int再去比較。

  ⑤、第五個打印結果為 false

  因為這個雖然值為10,但是我們都是通過 new 關鍵字來創建的兩個對象,是不存在緩存的概念的。兩個用new關鍵字創建的對象用 == 進行比較,結果當然為 false。

5、測試

	Integer a = 1;
	Integer b = 2;
	Integer c = 3;
	Integer d = 3;
	
	Integer e = 321;
	Integer f = 321;
	
	Long g = 3L;
	Long h = 2L;
	
	System.out.println(c == d); 
	System.out.println(e == f); 
	System.out.println(c == (a + b)); 
	System.out.println(c.equals((a+b)));
	System.out.println(g == (a+b));
	System.out.println(g.equals(a+b));
	System.out.println(g.equals(a+h));

  反編譯結果:

  

 

  打印結果為:

true
false
true
true
true
false
true

  分析:第一個和第二個結果沒什么疑問,Integer類在-128到127的緩存問題;

  第三個由於  a+b包含了算術運算,因此會觸發自動拆箱過程(會調用intValue方法),==比較符又將左邊的自動拆箱,因此它們比較的是數值是否相等。

  第四個對於c.equals(a+b)會先觸發自動拆箱過程,再觸發自動裝箱過程,也就是說a+b,會先各自調用intValue方法,得到了加法運算后的數值之后,便調用Integer.valueOf方法,再進行equals比較。

  第五個對於 g == (a+b),首先計算 a+b,也是先調用各自的intValue方法,得到數值之后,由於前面的g是Long類型的,也會自動拆箱為long,==運算符能將隱含的將小范圍的數據類型轉換為大范圍的數據類型,也就是int會被轉換成long類型,兩個long類型的數值進行比較。

  第六個對於 g.equals(a+b),同理a+b會先自動拆箱,然后將結果自動裝箱,需要說明的是 equals 運算符不會進行類型轉換。所以是Long.equals(Integer),結果當然是false

  第七個對於g.equals(a+h),運算符+會進行類型轉換,a+h各自拆箱之后是int+long,結果是long,然后long進行自動裝箱為Long,兩個Long進行equals判斷。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM