為什麼在Java中使用自動裝箱和拆箱?




autoboxing (6)

自動裝箱是Java編譯器在原始類型及其對應的對象包裝器類之間進行的自動轉換。 例如,將int轉換為Integer,將double轉換為Double,依此類推。 如果轉換過程相反,這稱為拆箱。

那麼,為什麼我們需要它?為什麼要在Java中使用自動裝箱和拆箱呢?


ArrayList不支持基本類型,僅支持類。 但是我們需要使用原始類型,例如int,double等。

ArrayList<String> strArrayList = new ArrayList<String>(); // is accepted.

ArrayList<int> intArrayList = new ArrayList<int>(); // not accepted.

Integer類將原始類型int的值包裝在一個對像中。因此可以接受下面的代碼。

ArrayList<Integer> intArrayList = new ArrayList<Integer>(); // is accepted.

我們可以使用add(value)方法添加一個值。 要添加一個字符串值,在strArrayList代碼中說“ Hello”只是

strArrayList.add("Hello");  

並添加一個int值說54我們可以寫

intArrayList.add(54);

但是當我們寫intArrayList.add(54); 編譯器轉換為以下行

intArrayList.add(Integer.valueOf(54)); 

因為intArrayList.add(54)很容易並且在用戶方面更容易接受,所以編譯器會做艱鉅的工作,即 intArrayList.add(Integer.valueOf(54)); 這是自動裝箱。

同樣,要檢索值,我們只需鍵入intArrayList.get(0)並將編譯器轉換為 <code>intArrayList.get(0).intValue(); 這是自動拆箱。


一些數據結構只能接受對象,而不能接受原始類型。

示例:HashMap中的鍵。

有關更多信息,請參 見此 問題: HashMap和int作為鍵

還有其他一些很好的理由,例如數據庫中的“ int”字段,也可以為NULL。 Java中的int不能為null; 整數引用可以。 自動裝箱和拆箱提供了一種避免在轉換中來回編寫多餘代碼的功能。


從JDK 5開始,java添加了兩個重要功能:自動裝箱和自動拆箱。 AutoBoxing 是一個過程,只要需要這樣的對象,就會自動將原始類型封裝在等效的包裝器中。 您不必顯式構造對象。 自動拆箱 是一個過程,通過該過程可以在需要封裝的對象的值時從其自動提取封裝對象的值。 您不需要調用諸如 intValue() doubleValue()之類的方法

自動裝箱和自動拆箱的添加大大 簡化了編寫算法 ,消除了手動裝箱和裝箱值的誘餌。 避免錯誤 也很有幫助。 對於 僅對對象進行操作的 泛型來說 ,這也非常重要。 最後,自動裝箱有助於使用 Collections Framework


自動裝箱:將原始值轉換為相應包裝器類的對象。

拆箱:將包裝器類型的對象轉換為其對應的原始值

// Java program to illustrate the concept 
// of Autoboxing and Unboxing 
import java.io.*; 

class GFG 
{ 
    public static void main (String[] args) 
    { 
        // creating an Integer Object 
        // with value 10. 
        Integer i = new Integer(10); 

        // unboxing the Object 
        int i1 = i; 

        System.out.println("Value of i: " + i); 
        System.out.println("Value of i1: " + i1); 

        //Autoboxing of char 
        Character gfg = 'a'; 

        // Auto-unboxing of Character 
        char ch = gfg; 
        System.out.println("Value of ch: " + ch); 
        System.out.println("Value of gfg: " + gfg); 

    } 
} 

原始(非對象)類型在效率上有合理性。

基本類型 int, boolean, double 是立即數據,而 Object 是引用。 因此,字段(或變量)

int i;
double x;
Object s;

需要本地內存4 + 8 + 8? 對於對象,僅存儲對內存的引用(地址)。

使用對象包裝器 Integer, Double 和其他包裝器 Integer, Double 將引入一個間接引用,該引用指向堆內存中的某些Integer / Double實例。

為什麼需要拳擊?

這是相對范圍的問題。 在將來的java中,計劃將能夠具有 ArrayList<int> ,從而提升基本類型。

答: 目前,ArrayList僅適用於對象,為對象引用保留空間,並同樣管理垃圾收集。 因此, 泛型類型 是對象子級。 因此,如果要使用浮點值的ArrayList,則需要將Double包裹在Double對像中。

Java與模板的傳統C ++有所不同:C ++類 vector<string>, vector<int> 將創建兩個編譯產品。 Java設計只需要一個ArrayList.class,而不需要為每個參數類型都使用一個新的編譯產品。

因此,在沒有裝箱到對象的情況下,將需要為每次出現的參數類型編譯類。 確切地說:每個集合或容器類都需要Object,int,double,boolean的版本。 Object的版本將處理所有子類。

實際上,Java SE已經對IntBuffer,CharBuffer,DoubleBuffer等實現了這樣的多樣化需求,它們可以對int,char和double進行操作。 通過從常見來源 生成 這些來源,以一種不可靠的方式解決了該問題。


為什麼我們要開箱?

使編寫混合原語及其面向對象(OO)替代品的代碼更舒適/更省力。

為什麼我們有原語及其面向對象的替代方法?

基本類型不是類(與C#不同),因此它們不是 Object 子類,並且不能被覆蓋。

出於性能方面的考慮,我們擁有諸如 int 原語,出於OO編程的優勢而擁有諸如 Integer 之類的 Object 替代品,並且作為次要點,它們具有實用程序常量和方法的良好位置(Integer.MAX_VALUE和 Integer.toString(int) ) 。

使用泛型( List<Integer> )最容易看到OO的好處,但不限於此,例如:

Number getMeSome(boolean wantInt) {

    if (wantInt) {
        return Integer.MAX_VALUE;
    } else {
        return Long.MAX_VALUE;
    }
}




autoboxing