java包裝類的小結

轉載自 http://macemers.iteye.com/blog/860631

Java包裝類,Wrapper~由於在java中,數據類型總共可分爲兩大種,基本數據類型(值類型)和類類型(引用數據類型)。基本類型的數據不是對象,所以對於要將數據類型作爲對象來使用的情況,java提供了相對應的包裝類。對於8種數據類型的包裝類分別是:

int—Integer
char—Character
float—Float
double—Double
byte—Byte
short—Short
long—Long
boolean–Boolean

java中除了Float,Double之外,都提供了常量池,但只有數值在-128~127之間纔會使用常量池。

所謂裝箱,就是把基本類型用它們相對應的引用類型包起來,使它們可以具有對象的特質,如我們可以把int型包裝成Integer類的對象,或者把double包裝成Double,等等。

所謂拆箱,就是跟裝箱的方向相反,將Integer及Double這樣的引用類型的對象重新簡化爲值類型的數據

J2SE5.0後提供了自動裝箱與拆箱的功能,此功能事實上是編譯器來幫您的忙,編譯器在編譯時期依您所編寫的方法,決定是否進行裝箱或拆箱動作。

自動裝箱的過程:每當需要一種類型的對象時,這種基本類型就自動地封裝到與它相同類型的包裝中。

自動拆箱的過程:每當需要一個值時,被裝箱對象中的值就被自動地提取出來,沒必要再去調用intValue()和doubleValue()方法。

自動裝箱,只需將該值賦給一個類型包裝器引用,java會自動創建一個對象。例如:

Integer i=100;//沒有通過使用new來顯示建立,java自動完成。

自動拆箱,只需將該對象值賦給一個基本類型即可。例如:int j=i;

int i = 10;
Integer j =new Integer(i); //手動裝箱操作  
int k = j.intValue();      //手動拆箱操作  

int i = 11;
Integer j = i; //自動裝箱
int k = j //自動拆箱

然而在Integer的自動裝拆箱會有些細節值得注意:

public static void main(String[] args) {
    Integer a=100;
        Integer b=100;

        Integer c=200;
        Integer d=200;

        System.out.println(a==b);   //1
        System.out.println(a==100); //2

        System.out.println(c==d);   //3
        System.out.println(c==200); //4
   }

在java種,”==”是比較object的reference而不是value,自動裝箱後,abcd都是Integer這個Oject,因此“==”比較的是其引用。按照常規思維,1和3都應該輸出false。但結果是:
true
true
false
true

結果2和4,是因爲ac進行了自動拆箱,因此其比較是基本數據類型的比較,就跟int比較時一樣的,“==”在這裏比較的是它們的值,而不是引用。

對於結果1,雖然比較的時候,還是比較對象的reference,但是自動裝箱時,java在編譯的時候 Integer a = 100; 被翻譯成-> Integer a = Integer.valueOf(100);
關鍵就在於這個valueOf()的方法。

public static Integer valueOf(int i) {   
final int offset = 128;   
if (i >= -128 && i <= 127) { // must cache   
return IntegerCache.cache[i + offset];   
}   
return new Integer(i);   
}   
private static class IntegerCache {   
private IntegerCache(){}   
static final Integer cache[] = new Integer[-(-128) + 127 + 1];   
static {   
for(int i = 0; i < cache.length; i++)   
cache = new Integer(i - 128);   
}   
} 

根據上面的jdk源碼,java爲了提高效率,IntegerCache類中有一個數組緩存了值從-128到127的Integer對象。當我們調用Integer.valueOf(int i)的時候,如果i的值是>=-128且<=127時,會直接從這個緩存中返回一個對象,否則就new一個Integer對象。

public class TestWhile{ //1
  public static void main(String[] args)//2
  {
  Integer i=0;//3
  Integer j=0;//4
  // Integer i=new Integer(0);//5
  // Integer j=new Integer(0);//6
  while(i<=j & i>=j & i!=j)//7
  { //8
  System.out.println("0000");//9
  }

  }

}

那一行是拆箱?while循環裏的條件看似不成立,可爲什麼可以運行(去掉第5、6行的註釋後)?
解答:
這種情況下,循環不能運行。
對於Integer類型,<,<=,>,>=操作將導致拆箱操作,也就是調用Integer的intValue()方法得到相應的基本類型值,然後比較。
但是,==,!=比較的,是對象的引用(Reference)。

Integer i = 0;//3
Integer j = 0;//4
這兩句使用裝箱操作,也就是調用Integer.valueOf(int i);注意,不是使用new。
由於0在 -128–127之間,根據上述,i和j引用的是同一個對象。
綜上,i<=j & i>=j & i!=j中,
i<=j 和 i>=j都成立,而i!=j不成立,因爲i和j引用的是同一個對象。

故此,循環不會執行。

註釋掉3,4兩句,使用5,6兩句時,i和j引用的不是同一個對象,所以i!=j成立。i<=j & i>=j & i!=j成立,循環條件總是成立的,while (i <= j & i >= j & i != j)成爲無窮循環,不斷輸出。

總結,對於要比較Object的值,最穩妥的方法還是調用equals()這個方法(比較的是數值,或者用compareTo(包裝類),返回0時,說明相等),而不是使用==,因此會比較其引用。

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