首頁技術(shù)文章正文

Java培訓(xùn): 包裝類概述

更新時間:2022-10-17 來源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

  - Java中有8中基本數(shù)據(jù)類型,分別是:

1665971512740_1.jpg

  包裝類就是這8種數(shù)據(jù)類型所對應(yīng)的引用數(shù)據(jù)類型,分別是:

1665971528418_2.jpg

  - 可能有同學(xué)會問:Java為什么要給基本數(shù)據(jù)類型提供對應(yīng)的引用數(shù)據(jù)呢?

  - 第一,Java是面向?qū)ο蟮恼Z言,給它們設(shè)計對應(yīng)的引用類型,非常符合萬物皆對象的設(shè)計理念

  - 第二,有類,那么就會有屬性,會有方法。那么針對這些類型的一些數(shù)據(jù)操作可以變得更加簡單,比如說:

  - 如果要根據(jù)字節(jié)數(shù)計算int的取值范圍就有些麻煩,但是它的包裝類Integer就提供了`Integer.MIN_VALUE`和`Integer.MAX_VALUE`記錄了范圍數(shù)據(jù)

  - 第三,Java中集合和泛型作為經(jīng)常使用的對象,它們只支持引用數(shù)據(jù)類型,比如說,如果需要使用集合存儲int類型整數(shù)。那么直接聲明集合的泛型為int是不可以的,此時就可以使用它對應(yīng)的包裝類Integer

  - 所以結(jié)論就是:使用包裝類可以方便不同數(shù)據(jù)類型的相關(guān)操作,另外集合也會經(jīng)常用到包裝類!

  2. 自動裝箱

  - 既然包裝類有很好的使用價值,那么自然就是要創(chuàng)建它們的對象去使用。而自動裝箱就是一種可以很方便快捷的拿到它們對象的方式,幾種包裝類的設(shè)計非常相似,這里就以Integer舉例

  Integer num = 23;

  3. 自動拆箱

  - 和自動裝箱相反,自動拆箱指的就是可以將一個包裝類對象直接賦值給其對應(yīng)的基本數(shù)據(jù)類型變量,例如:

 Integer num = 23;
  int a = num;

  - 這種情況就是所謂的自動拆箱,其實底層是調(diào)用Integer包裝類的`intValue()`方法,返回了記錄的數(shù)據(jù)值23。以此類推,如果是Double,底層就是調(diào)用的`doubleValue()`方法獲取數(shù)據(jù)值返回。

  4. 常見操作

  - 基本數(shù)據(jù)類型轉(zhuǎn)字符串:

  - 靜態(tài)方法:toString(基本數(shù)據(jù)類型的數(shù)據(jù)值),例如:`String str = Integer.toString(23);`

  - 推薦使用String的靜態(tài)方法:valueOf(基本數(shù)據(jù)類型的數(shù)據(jù)值),例如:`String str = String.valueOf(20);`

  - 數(shù)值內(nèi)容的字符串轉(zhuǎn)基本數(shù)據(jù)類型:

  - 調(diào)用parseXXX的方法,例如:`int num = Integer.parseInt("66");`

  - 注意:如果字符串不是數(shù)值內(nèi)容,而是"a"、"b"、"中"...這樣的非數(shù)值,就會引發(fā)異常:NumberFormatException

  5. 面試題

  - 觀察以下代碼,說結(jié)果

Integer a = 127;
Integer b = 127;
System.out.println(a == b);


Integer c = Integer.valueOf(127);
System.out.println(a == c);

Integer d = new Integer(127);
System.out.println(a == d);

Integer x = 128;
Integer y = 128;
System.out.println(x == y);

  - 結(jié)果分別是:true,true,false,false

  - 原因:

  - Integer自動裝箱底層會調(diào)用valueOf()方法,源代碼:

public static Integer valueOf(int i) {
      if (i >= IntegerCache.low && i <= IntegerCache.high)
          return IntegerCache.cache[i + (-IntegerCache.low)];
      return new Integer(i);
  }

  - 可以看到,會拿數(shù)據(jù)值和Integer的一個靜態(tài)內(nèi)部類IntegerCache類的low屬性于high屬性做范圍判斷,其中l(wèi)ow的值是-128,high的值是127

  - 也就是說,調(diào)用valueOf()方法,會判斷數(shù)據(jù)是否在-128~127的范圍內(nèi)。如果在范圍內(nèi),就從靜態(tài)內(nèi)部類IntegerCache的一個cache數(shù)組屬性中獲取一個Integer對象

  - 如果不在這個范圍內(nèi),就是新new一個Integer對象

  - IntegerCache這個靜態(tài)內(nèi)部類有一個靜態(tài)代碼塊:

static {
      // high value may be configured by property
      int h = 127;
      String integerCacheHighPropValue =
          VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
      if (integerCacheHighPropValue != null) {
          try {
              h = Math.max(parseInt(integerCacheHighPropValue), 127);
              // Maximum array size is Integer.MAX_VALUE
              h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
          } catch( NumberFormatException nfe) {
              // If the property cannot be parsed into an int, ignore it.
          }
      }
      high = h;
 
      // Load IntegerCache.archivedCache from archive, if possible
      CDS.initializeFromArchive(IntegerCache.class);
      int size = (high - low) + 1;
 
      // Use the archived cache if it exists and is large enough
      if (archivedCache == null || size > archivedCache.length) {
          Integer[] c = new Integer[size];
          int j = low;
          for(int i = 0; i < c.length; i++) {
              c[i] = new Integer(j++);
          }
          archivedCache = c;
      }
      cache = archivedCache;
      // range [-128, 127] must be interned (JLS7 5.1.7)
      assert IntegerCache.high >= 127;
  }

  - 一般情況下,這段代碼第一個if不會進(jìn)入,所以high的值就被賦值127,經(jīng)過計算,size變量的值就是256。

  - 第二個if語句的條件通常是可以成立的,所以就創(chuàng)建了一個長度為256的Integer類型數(shù)組,通過一個for循環(huán),給這個數(shù)組就從-128開始賦值,一致賦值到127結(jié)束,剛好是256個。

  - 至此,內(nèi)部類中就出現(xiàn)了一個Integer類型數(shù)組,緩沖了256個Integer對象,對應(yīng)的數(shù)據(jù)范圍正好是:-128~127。

  - 那么通過以上分析可知,只要是通過自動裝箱或者valueOf()方法去獲取對象,只要數(shù)據(jù)范圍在-128~127,不管獲取多少次,都會從數(shù)組中去拿緩沖的對象,所以拿到的始終是同一個,所以判斷的結(jié)果就是true。

  - 但如果不在這個范圍內(nèi),就是去new一個新的Integer對象,會開辟一個新的對象空間,地址值肯定不一樣,所以結(jié)果就是false。

分享到:
在線咨詢 我要報名
和我們在線交談!