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




autoboxing (6)

為什麼我們有(聯合國)拳擊?

編寫代碼,我們混合原語及其面向對象(OO)替代方案更舒適/更簡潔。

為什麼我們有原始人和他們的OO替代品?

原始類型不是類(與C#不同),因此它們不是Object子類,不能被覆蓋。

出於性能原因,我們有像int這樣的原語,對於OO編程的好處,我有像Integer這樣的Object替代,並且作為一個小問題,為實用程序常量和方法(Integer.MAX_VALUE和Integer.toString(int) )提供了一個很好的位置。

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

Number getMeSome(boolean wantInt) {

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

自動裝箱是Java編譯器在基元類型和相應的對象包裝類之間進行的自動轉換。 例如,將int轉換為Integer,將double轉換為Double,依此類推。 如果轉換是另一種方式,則稱為拆箱。

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


一些數據結構只能接受對象,不能接受基本類型。

示例:HashMap中的鍵。

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

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


Auto Boxing 用於將原始數據類型轉換為其包裝類對象。 包裝類提供了對基本類型執行的各種功能。 最常見的例子是:

int a = 56;
Integer i = a; // Auto Boxing

這是需要的,因為程序員很容易直接編寫代碼,JVM將負責Boxing和Unboxing。

當我們使用java.util.Collection類型時,Auto Boxing也派上用場。 當我們想要創建基本類型的集合時,我們不能直接創建基本類型的集合,我們只能創建對象的集合。 例如 :

ArrayList<int> al = new ArrayList<int>(); // not supported 

ArrayList<Integer> al = new ArrayList<Integer>(); // supported 
al.add(45); //auto Boxing 

包裝類

Java的8個基本類型(byte,short,int,float,char,double,boolean,long)中的每一個都有一個單獨的Wrapper類與它們相關聯。 這些Wrapper類具有預定義的方法,用於對原始數據類型執行有用的操作。

使用包裝類

String s = "45";
int a = Integer.parseInt(s); // sets the value of a to 45.

Wrapper類提供了許多有用的功能。 here查看java文檔

拆箱與Auto Boxing相反,我們將包裝類對象轉換回其原始類型。 這是由JVM自動完成的,這樣我們就可以使用包裝類進行某些操作,然後將它們轉換回原始類型,因為原語可以加快處理速度。 例如 :

Integer s = 45;
int a = s; auto UnBoxing;

對於使用對象的集合,僅使用自動拆箱。 就是這樣 :

ArrayList<Integer> al = new ArrayList<Integer>();
al.add(45);

int a = al.get(0); // returns the object of Integer . Automatically Unboxed . 

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

自動裝箱和自動拆箱的添加極大地簡化了編寫算法 ,消除了手動裝箱和取消裝箱值的誘餌。 避免錯誤也很有幫助。 對於只對物體進行操作的仿製藥來說 ,這一點也非常重要。 最後,自動裝箱有助於使用集合框架


原始(非對象)類型在效率方面具有正當性。

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

int i;
double x;
Object s;

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

使用Object包裝器Integer, Double等,可以引入一個間接,引用堆內存中的某個Integer / Double實例。

為什麼需要拳擊?

這是一個相對范圍的問題。 在未來的java中,計劃能夠使用ArrayList<int> ,解除基本類型。

答:現在,ArrayList僅適用於Object,為對象引用保留空間,同樣管理垃圾收集。 因此泛型類型是Object子類。 因此,如果想要一個浮點值的ArrayList,則需要在Double對像中包含double。

這裡的Java與傳統的C ++及其模板不同:C ++類vector<string>, vector<int>將創建兩個編譯產品。 Java設計有一個ArrayList.class,不需要為每個參數類型提供新的編譯產品。

因此,如果沒有裝箱到對象,則需要為每次出現的參數類型編譯類。 在concreto中:每個集合或容器類都需要Object,int,double,boolean的版本。 Object的版本將處理所有子類。

實際上,對於IntBuffer,CharBuffer,DoubleBuffer等的Java SE中已經存在對這種多樣化的需求,它們對int,char,double進行操作。 它通過從一個普通的源生成這些源來以一種黑客的方式解決。


因為它們是不同的類型,並且為了方便。 性能可能是原始類型的原因。







autoboxing