JavaRush /Java Blog /Random-TW /Java 中的自動裝箱與拆箱
DSergey_Kh
等級 12

Java 中的自動裝箱與拆箱

在 Random-TW 群組發布
在本文中,我們將了解 Java 中稱為自動裝箱/拆箱的功能。自動裝箱和拆箱是將原始類型轉換為物件類型的功能,反之亦然。 Java 中的自動裝箱和拆箱 - 1整個過程由Java執行環境(JRE)自動執行。但在實現這個功能時你應該小心,因為...... 它會影響程式的效能。

介紹

int在 JDK 1.5 以下的版本中,將、charfloat、 等原始資料類型轉換double為它們的包裝類別 Integer、Character、Float、Double並不容易。從 JDK 5 開始,自動實作將原始類型轉換為等效物件的功能。此屬性稱為自動裝箱。相反的過程分別是拆箱,即 將物件轉換為其對應的原始類型的過程。自動裝箱和拆箱的範例程式碼如下:
Integer integer = 9;
拆箱
int in = 0;
in = new Integer(9);
什麼時候使用自動裝箱和拆箱? Java 編譯器在下列條件下使用自動裝箱:
  • 當基本類型的值作為方法參數傳遞給方法時,需要對應包裝類別的物件。
  • 當將原始類型的值指派給對應包裝類別的變數。
考慮以下範例: 清單 1:顯示自動裝箱的簡單程式碼
public int sumEvenNumbers(List<Integer> intList ) {
int sum = 0;
for (Integer i: intList )
if ( i % 2 == 0 )
sum += i;
return sum;
}
在 jdk 1.5 之前,上述程式碼會導致編譯錯誤,因為餘數運算子 % 和一元加 += 無法套用於包裝類別。但在 jdk 1.5 以上版本中,這段程式碼編譯沒有錯誤,將 Integer 轉換為int. Java 編譯器在下列條件下使用拆箱:
  • 當物件作為參數傳遞給需要對應基本類型的方法。
  • 當一個物件被指派給對應原始類型的變數。
考慮以下範例: 清單 2:顯示拆箱的簡單程式碼
import java.util.ArrayList;
import java.util.List;

public class UnboxingCheck {

public static void main(String[] args) {
Integer in = new Integer(-8);

// 1. Распаковка через вызов метода
int absVal = absoluteValue(in);
System.out.println("absolute value of " + in + " = " + absVal);

List<Double> doubleList = new ArrayList<Double>();

// Автоупаковка через вызов метода
doubleList.add(3.1416);

// 2. Распаковка через присвоение
double phi = doubleList.get(0);
System.out.println("phi = " + phi);
}

public static int absoluteValue(int i) {
return (i < 0) ? -i : i;
}
}
自動裝箱和拆箱允許開發人員編寫易於閱讀和理解的程式碼。下表顯示了原始資料類型及其相應的包裝物件。
原始型 外殼類
布林值 布林值
位元組 位元組
字元 特點
漂浮 漂浮
整數 整數
長的 長的
短的 短的
表 1:帶有比較運算子的基本類型和等效包裝類別 自動裝箱和拆箱可以與比較運算子一起使用。以下程式碼片段說明了這是如何發生的: 清單 3:顯示使用比較運算子進行自動裝箱和拆箱的範例程式碼
public class BoxedComparator {
  public static void main(String[] args) {
      Integer in = new Integer(25);
      if (in < 35)
          System.out.println("Value of int = " + in);
  }
}
方法重載時的自動打包和解包 方法重載時的自動打包和解包依照下列規則進行:
  • 當需要在擴展和封裝之間進行選擇時,擴展會「擊敗」封裝;擴展是更好的選擇。
清單 4:顯示重載好處的範例程式碼
public class WideBoxed {
  public class WideBoxed {
  static void methodWide(int i) {
       System.out.println("int");
   }

  static void methodWide( Integer i ) {
      System.out.println("Integer");
  }

  public static void main(String[] args) {
      short shVal = 25;
      methodWide(shVal);
  }
 }
}
程式輸出類型int
  • 擴展勝過可變數量的參數 在需要在擴展和可變數量的參數之間進行選擇的情況下,擴展是更可取的。
清單 5:顯示重載好處的範例程式碼
public class WideVarArgs {

    static void methodWideVar(int i1, int i2) {
      System.out.println("int int");
    }

    static void methodWideVar(Integer... i) {
       System.out.println("Integers");
    }

   public static void main( String[] args) {
       short shVal1 = 25;
      short shVal2 = 35;
     methodWideVar( shVal1, shVal2);
   }
  }
  • 打包優於可變數量的參數 在需要在打包和可變數量的參數之間進行選擇的情況下,打包是更可取的。
清單 6:展示重載好處的範例程式碼
public class BoxVarargs {
     static void methodBoxVar(Integer in) {
         System.out.println("Integer");
     }

     static void methodBoxVar(Integer... i) {
         System.out.println("Integers");
     }
     public static void main(String[] args) {
         int intVal1 = 25;
         methodBoxVar(intVal1);
    }
}
使用自動打包時應記住以下事項: 眾所周知,每個好的功能都有一個缺點。汽車包裝在這方面也不例外。開發人員在使用此功能時應牢記的一些重要注意事項:
  • 將物件與「==」運算子進行比較可能會令人困惑,因為它可以應用於基本類型和物件。當此運算子應用於物件時,它實際上會比較物件的引用,而不是物件本身。
清單 7:顯示比較的範例程式碼。
public class Comparator {
   public static void main(String[] args) {
     Integer istInt = new Integer(1);
       Integer secondInt = new Integer(1);

       if (istInt == secondInt) {
         System.out.println("both one are equal");

       } else {
          System.out.println("Both one are not equal");
      }
   }
}
  • 將物件和原始類型與相等和關係運算子混合。如果我們將原始類型與物件進行比較,則該物件將被拆箱,NullPointerException如果該物件null.
  • 對象緩存。該方法valueOf()創建一個它緩存的原始物件的容器。由於值的快取範圍為 -128 到 127(含),因此這些快取物件的行為可能有所不同。
  • 性能下降。自動裝箱或拆箱會降低應用程式效能,因為它會建立一個不需要的對象,迫使垃圾收集器更頻繁地運行。
AutoBoxing 的缺點 儘管 AutoBoxing 有許多優點,但它也有以下缺點: 清單 8:顯示效能問題的範例程式碼。
public int sumEvenNumbers(List intList) {
          int sum = 0;
          for (Integer i : intList) {
              if (i % 2 == 0) {
                  sum += i;
              }
          }
         return sum;
   }
在這一段程式碼中,sum +=i 它將被擴展為sum = sum + i. 從「+」運算子開始,JVM 開始拆箱,因為「+」運算子不能套用於 Integer 物件。然後結果被自動打包回來。在JDK 1.5之前,資料類型int和Integer是不同的。在方法重載的情況下,使用這兩種類型沒有問題。隨著自動打包/拆包的出現,這變得更加困難。一個例子是remove()中的重載方法ArrayList。該類別ArrayList有兩個刪除方法 -remove(index)remove(object)。在這種情況下,不會發生方法重載,並且會使用適當的參數來呼叫相應的方法。

結論

自動裝箱是將原始資料型別隱式轉換為對應包裝類別(物件)的機制。編譯器透過方法valueOf()將原始型別轉換為對象,透過方法IntValue()doubleValue()取得對象的原始型別。自動裝箱將布林類型轉換boolean為布林型、byte位元組型char、字元型 float、浮點型、int整數型、long長整型、short短整型。拆包以相反的方向進行。 來源文章
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION