java包裝類和值類型的關係

java包裝類老是讓人疑惑 它與值類型究竟是怎麼樣一種關係? 本文將以int和Integer爲例來探討它們的關係java

 

java值類型有int short char boolean byte long float double程序員

除此以外的類型皆爲引用類型 引用類型和值類型的區別你們都很熟悉 在這裏就很少說了c#

 

引用類型和值類型有一個很重要的區別 那就是引用類型繼承Object類 值類型不是jvm

而java不少泛型容器都要求類型繼承Object 調用虛方法要求必須是引用類型 很明顯這些值類型不知足這個要求 怎麼辦? 包裝類應運而生函數

 

包裝類有Integer Short Char Boolean Byte Long Float Double和上文的值類型是對應的spa

 

既然包裝類是引用類型 那麼他就應該能夠傳遞到別的方法被修改設計

public static void change(Integer a)
{
    a *= 6;
}
public static void main(String[] args)
{
    Integer integer = new Integer(5);
    change(integer);
    System.out.println(integer);
}

然而 以上程序輸出的結果是5 跟下文代碼的結果是相同的 這是爲何?code

public static void change(int a)
{
    a *= 6;
}
public static void main(String[] args) {
    int integer = 5;
    change(integer);
    System.out.println(integer);
}

這就得從包裝類的設計講起了 前文說過 包裝類是爲了可以彌補值類型的缺陷而設計的對象

有了包裝類後 對於一個整數的表達就出現了int和Integer這兩個類型 一個是值類型一個是引用類型 這會讓程序員在使用過程當中產生困擾blog

爲了消除這種困擾 java在設計時就儘量地減小它們的區別 讓包裝類表現得如同值類型 因而就出現了上文的結果

 

這種區別減小是經過編譯器完成 若是咱們查看編譯好的字節碼 就會看到上文的Integer實際上是這樣工做的

public static void change(Integer a)
{
    a = Integer.valueOf(a.intValue() * 6);
}
public static void main(String[] args)
{
    Integer integer = new Integer(5);
    change(integer);
    System.out.println(integer);
}

a*=6的結果返回了一個新的Integer對象

因此也就不可能修改傳入的Integer的值了 就算要修改   Integer這個類的成員是final修飾 仍是沒法修改

 

而後我還發現了一點Object強制轉換爲int

Object obj = new Integer(5);
int a = (int)obj;

在編譯器處理後 實際上是這樣的 這也進一步說明引用類型和值類型徹底是兩個世界的東西

Object obj = new Integer(5);
int a = ((Integer)obj).intValue();

 

題外話:

對於java的值類型和包裝類的設計 我十分不喜歡

java中一切都是對象 值類型除外

對於一樣一個整數類型 分紅int Interger兩個類型感受很不必

 

c#的int是繼承Object的 在須要調用虛函數的時候會自動裝箱

int a = 233;
a.ToString()

在jvm上跑的Kotlin 它有一套特殊映射法則 把Int根據狀況自動變換成int和Integer 而在語言層面上只有一個Int

Int a = 233;
a.toString();

 

可是到了java 你只能這樣

int a = 233;
new Integer(a).toString();

或者是這樣

int a = 233;
((Integer)a).toString();

 

END

相關文章
相關標籤/搜索