JavaRush /Java Blog /Random-TW /包裝、拆包和包裝

包裝、拆包和包裝

在 Random-TW 群組發布
你好!您已經非常熟悉原始類型,並且經常使用它們。 包裝、拆包和包裝 - 1程式設計中的原語,特別是 Java 中的原語,有很多優點:它們佔用很少的內存,從而提高了程式的效率,並且被明確地劃分為值的範圍。然而,在學習Java的過程中,我們不只一次重複著,就像一句口頭禪,「在Java中一切皆物件」。但原語是對這些話的直接反駁。它們不是物體。那麼「一切皆對象」的原則是錯誤的嗎?並不真地。在 Java 中,每個基本型別都有它的孿生兄弟,即包裝類別( Wrapper)。什麼是包裝紙? 包裝器是一個特殊的類,它在其內部儲存原語的值。 但由於這是一個類,它可以創建自己的實例。它們將在內部儲存必要的原始值,同時是真實的物件。包裝類別的名稱與相應基元的名稱非常相似,或完全一致。因此,記住它們會很容易。
原始資料型別的包裝類
原始資料類型 包裝類
整數 整數
短的 短的
長的 長的
位元組 位元組
漂浮 漂浮
雙倍的 雙倍的
字元 特點
布林值 布林值
包裝類別物件的建立就像任何其他物件一樣:
public static void main(String[] args) {

   Integer i = new Integer(682);

   Double d = new Double(2.33);

   Boolean b = new Boolean(false);
}
包裝類別可讓您減輕原始類型的缺點。最明顯的一點是原語沒有方法。例如,它們沒有 method toString(),因此您無法將數字轉換int為字串。但有了包裝類Integer就很容易了。
public static void main(String[] args) {

   Integer i = new Integer(432);

   String s = i.toString();
}
反向轉換也會遇到困難。假設我們有一個我們確定包含數字的字串。然而,在基本類型的情況下,int我們將無法從字串中獲取該數字並將其實際轉換為數字。但多虧了包裝類,我們現在有了這個機會。
public static void main(String[] args) {

   String s = "1166628";

   Integer i = Integer.parseInt(s);

   System.out.println(i);
}
輸出: 1166628 我們已成功從字串中檢索到數字並將其指派給引用變數Integer i。順便說一下,關於連結。您已經知道參數以不同的方式傳遞給方法:基元按值傳遞,物件按參考傳遞。您可以在建立方法時使用這些知識:例如,如果您的方法適用於小數,但您需要透過引用傳遞的邏輯,則可以將參數傳遞給方法而Double/Float不是double/float. 另外,除了方法之外,包裝類別還有靜態字段,使用起來非常方便。例如,假設您現在面臨一項任務:將最大可能的數字列印到控制台 int,然後列印最小可能的數字。 這項任務似乎很簡單,但如果沒有谷歌,你仍然很難完成它。包裝類可以輕鬆讓您解決以下「日常問題」:
public class Main {
   public static void main(String[] args) {

       System.out.println(Integer.MAX_VALUE);
       System.out.println(Integer.MIN_VALUE);
   }
}
這些領域可以讓你不會從更嚴肅的任務中分心。更不用說在列印數字2147483647(這正是 MAX_VALUE)的過程中,輸入錯誤也就不足為奇了:) 另外,在之前的一講中,我們已經提請注意這樣一個事實:包裝類別的物件是不可變的(Immutable)
public static void main(String[] args) {

   Integer a = new Integer(0);
   Integer b = new Integer(0);

   b = a;
   a = 1;
   System.out.println(b);
}
輸出: 0引用 最初指向的物件а沒有改變其狀態,否則值b也會改變。與 一樣String,不是更改包裝器物件的狀態,而是在記憶體中建立一個全新的物件。為什麼 Java 的創建者最終決定在該語言中保留原始類型?既然一切都應該是對象,而且我們已經有了可以用來表達原語表達的一切的包裝類,為什麼不把它們留在語言中並刪除原語呢?答案很簡單——性能。原始類型之所以被稱為原始類型,是因為它們缺乏物件的許多「重」特徵。是的,一個物件有很多方便的方法,但你並不總是需要它們。有時您只需要數字 33 或 2.62 或true/的值false。在物件的所有好處都無關緊要且程式不需要運行的情況下,基元會做得更好。

自動裝箱/自動拆箱

Java中原語及其包裝類別的特性之一是自動裝箱/自動拆箱, 包裝、拆包和包裝 - 2 讓我們來理解這個概念。正如您和我之前已經了解到的,Java 是一種物件導向的語言。這意味著所有用Java編寫的程式都是由物件組成的。基元不是對象。但是,可以為包裝類別變數指派基本類型的值。這個過程稱為自動裝箱以同樣的方式,可以將原始類型的變數指派給包裝類別的物件。這個過程稱為自動拆箱。例如:
public class Main {
   public static void main(String[] args) {
       int x = 7;
       Integer y = 111;
       x = y; // auto unpacking
       y = x * 123; // autopacking
   }
}
在第 5 行,我們將 y 的值賦給基元 x,y 是包裝類別的物件Integer。正如您所看到的,不需要執行任何其他操作:編譯器知道這一點,int事實上Integer,是同一件事。這是自動拆包。第 6 行中的自動裝箱也發生了同樣的事情:物件 y 很容易被指派基元的值 (x*123)。這是自動打包的範例。這就是為什麼添加“自動”一詞的原因:將原始引用分配給其包裝類別的物件(反之亦然),您不需要執行任何操作,一切都會自動發生。方便吧?:) 自動打包/自動解包的另一個很大的便利體現在方法的操作上。事實上,方法參數也受到自動打包和自動解包的影響。並且,例如,如果其中一個將兩個物件作為輸入Integer,我們可以輕鬆地向那裡傳遞普通基元int
public class Main {
   public static void main(String[] args) {

       printNumber(7);//regular int, even without a variable
   }

   public static void printNumber(Integer i) {
       System.out.println("You entered a number" + i);
   }
}
輸出: 您輸入了數字 7。 反之亦然:
public class Main {
   public static void main(String[] args) {

       printNumber(new Integer(632));
   }

   public static void printNumber(int i) {
       System.out.println("You entered a number" + i);
   }
}
要記住的重要一點:自動裝箱和拆箱不適用於陣列
public class Main {
   public static void main(String[] args) {

       int[] i = {1,2,3,4,5};

       printArray(i);//error, won't compile!
   }

   public static void printArray(Integer[] arr) {
       System.out.println(Arrays.toString(arr));
   }
}
嘗試將基元數組傳遞給以物件數組作為輸入的方法將導致編譯錯誤。最後,我們再次簡單比較一下原語和包裝 原語:
  • 有性能優勢
包裝紙:
  • 它們讓你不違反「一切皆對象」的原則,這樣數字、符號和布林值true/false就不會脫離這個概念
  • 透過提供方便的方法和欄位來擴展使用這些值的能力
  • 當某些方法只能與物件一起使用時是必要的
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION