首頁  >  文章  >  Java  >  Java中實作自動拆裝箱的簡單介紹

Java中實作自動拆裝箱的簡單介紹

黄舟
黄舟原創
2017-10-12 10:15:221178瀏覽

這篇文章主要為大家詳細介紹了Java自動拆裝箱的相關資料,具有一定的參考價值,有興趣的小夥伴們可以參考一下

在面試過程中,常常會有面試官問到基礎的問題的時候都會問到Java的拆裝箱,關於這個問題其實不是很難,但是如果平時進行自學的時候不是注意,就可能一臉懵逼,所以筆者就這個問題進行一些總結,共同促進!

一、拆裝箱概念

所謂的拆裝箱,就是自從JDK1.5之後,java的基本型別與引用型別之間的相互轉換。

1.1拆箱

拆箱就是把Long,Integer,Double,Float 等將基本資料型別的首字母大寫的對應的引用型別轉換為基本資料型別的動作就叫拆箱。

1.2裝箱

裝箱就是把byte ,int ,short, long ,double,float,boolean,char 這些Java的基本資料型別在定義資料型別時不宣告為相對應的引用類型,在編譯器的處理下自動轉換成引用類型的動作就叫做裝箱。

二、拆裝箱的相關應用程式

在JDK1.5後,當我們進行基本類型和引用型別的轉換的時候就會方便:


package com.hzp.CZX;
/**
 * 测试拆装箱
 * @author 夜孤寒
 * @version 1.1.1
 */
public class TestDemo {
  /**
   * 拆装箱JDK1.5后
   */
  public static void first(){
    Integer i=7;//基本类型-->引用类型
    int j=i;//引用类型-->基本类型
    System.out.println(j);
  }
  /**
   * 拆装箱JDK1.4
   */
  public static void second(){
    Integer i=new Integer(78);
    int j=i.intValue();
    System.out.println(j);
  }
  /**
   * 测试方法
   * @param args
   */
  public static void main(String[] args) {
    first();
    second();
  }
}

上面介紹了關於拆裝箱的一些基本點和使用方式,但是要使用拆裝箱的話還有一些注意點需要注意,下面將這些注意點進行一些總結。

三、注意點

先貼一段程式碼如下:


package com.ygh.CZX;
/**
 * 关于java的拆装箱范围剖析
 * @author 夜孤寒
 * @version 1.1.1
 */
public class Test {
  /**
   * 以Integer类型为例
   */
  public static void first(){
    Integer i=new Integer(124);
    Integer j=new Integer(124);
    System.out.println(i==j);//false
    Integer a1=-128;
    Integer a2=-128;
    System.out.println(a1==a2);//true
    Integer b1=-129;
    Integer b2=-129;
    System.out.println(b1==b2);//false
    Integer c1=127;
    Integer c2=127;
    System.out.println(c1==c2);//true
    Integer d1=128;
    Integer d2=128;
    System.out.println(d1==d2);//false
  }
  public static void main(String[] args) {
    first();
    
  }
}

簡單解釋一下:

第一個結果為false的原因是因為創建了不同的對象,所以兩者不一樣;

但是第二個和第三個的結果為什麼不一樣?

下面貼出關於Integer類別的源碼,從源碼的角度來分析這個問題:


  /**
   * Returns an {@code Integer} instance representing the specified
   * {@code int} value. If a new {@code Integer} instance is not
   * required, this method should generally be used in preference to
   * the constructor {@link #Integer(int)}, as this method is likely
   * to yield significantly better space and time performance by
   * caching frequently requested values.
   *
   * This method will always cache values in the range -128 to 127,
   * inclusive, and may cache other values outside of this range.
   *
   * @param i an {@code int} value.
   * @return an {@code Integer} instance representing {@code i}.
   * @since 1.5
   */
  public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
      return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
  }

上面的程式碼是說,進行自動拆裝箱的時候,是有一個範圍的,一旦超出這個範圍,那麼指向的就不是同一個對象,而是返回一個新創建的對象了,這個範圍在Integer類中的一個內部私有類IntegerCache可以體現出來,原始碼如下:


 private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];

    static {
      // high value may be configured by property
      int h = 127;
      String integerCacheHighPropValue =
        sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
      if (integerCacheHighPropValue != null) {
        try {
          int i = parseInt(integerCacheHighPropValue);
          i = Math.max(i, 127);
          // Maximum array size is Integer.MAX_VALUE
          h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        } catch( NumberFormatException nfe) {
          // If the property cannot be parsed into an int, ignore it.
        }
      }
      high = h;

      cache = new Integer[(high - low) + 1];
      int j = low;
      for(int k = 0; k < cache.length; k++)
        cache[k] = new Integer(j++);

      // range [-128, 127] must be interned (JLS7 5.1.7)
      assert IntegerCache.high >= 127;
    }

    private IntegerCache() {}
  }

從這裡我們可以看出,範圍值為[-128,127]之間。

注意,Integer、Short、Byte、Character、Long這幾個類別的valueOf方法的實作是類似的。
Double、Float的valueOf方法的實作是類似的。

總結:這些進行自動拆裝箱的基本型別的範圍如下:

1. boolean型別的值

2.所有的byte的值

3.在-128~127的short類型的值

4.在-128~127的int型別的值

5.在\ u0000~\ u00ff 之間的char類型的值

而其中double和float又有所不同,我們就以double為例子,貼出程式碼討論:


package com.ygh.CZX;

/**
 * 关于java的拆装箱范围剖析
 * 
 * @author 夜孤寒
 * @version 1.1.1
 */
public class Test {
  /**
   * Double
   */
  public static void first() {
    Double i1 = 100.0;
    Double i2 = 100.0;
    Double i3 = 200.0;
    Double i4 = 200.0;
    System.out.println(i1 == i2);//false
    System.out.println(i3 == i4);//false
  }
  /**
   * 测试方法
   */
  public static void main(String[] args) {
    first();
  }
}

注意為什麼上面的程式碼的輸出結果都是false呢?同樣的我們依舊以Double類別中的valueOf方法來討論,貼出原始碼就一目了然了:


  /**
   * Returns a {@code Double} instance representing the specified
   * {@code double} value.
   * If a new {@code Double} instance is not required, this method
   * should generally be used in preference to the constructor
   * {@link #Double(double)}, as this method is likely to yield
   * significantly better space and time performance by caching
   * frequently requested values.
   *
   * @param d a double value.
   * @return a {@code Double} instance representing {@code d}.
   * @since 1.5
   */
  public static Double valueOf(double d) {
    return new Double(d);
  }

也就是說不管你的double是什麼範圍的值,他都是給你回一個新的物件。 float同double,就不過多贅述了。

以上就是筆者對於拆裝箱的一些整理,如果讀者有不同的看法可以在評論區提出,筆者再進行修改!

以上是Java中實作自動拆裝箱的簡單介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn