更新時間:2022-10-17 來源:黑馬程序員 瀏覽量:
- Java中有8中基本數據類型,分別是:
包裝類就是這8種數據類型所對應的引用數據類型,分別是:
- 可能有同學會問:Java為什么要給基本數據類型提供對應的引用數據呢?
- 第一,Java是面向對象的語言,給它們設計對應的引用類型,非常符合萬物皆對象的設計理念
- 第二,有類,那么就會有屬性,會有方法。那么針對這些類型的一些數據操作可以變得更加簡單,比如說:
- 如果要根據字節數計算int的取值范圍就有些麻煩,但是它的包裝類Integer就提供了`Integer.MIN_VALUE`和`Integer.MAX_VALUE`記錄了范圍數據
- 第三,Java中集合和泛型作為經常使用的對象,它們只支持引用數據類型,比如說,如果需要使用集合存儲int類型整數。那么直接聲明集合的泛型為int是不可以的,此時就可以使用它對應的包裝類Integer
- 所以結論就是:使用包裝類可以方便不同數據類型的相關操作,另外集合也會經常用到包裝類!
2. 自動裝箱
- 既然包裝類有很好的使用價值,那么自然就是要創建它們的對象去使用。而自動裝箱就是一種可以很方便快捷的拿到它們對象的方式,幾種包裝類的設計非常相似,這里就以Integer舉例
Integer num = 23;
3. 自動拆箱
- 和自動裝箱相反,自動拆箱指的就是可以將一個包裝類對象直接賦值給其對應的基本數據類型變量,例如:
Integer num = 23; int a = num;
- 這種情況就是所謂的自動拆箱,其實底層是調用Integer包裝類的`intValue()`方法,返回了記錄的數據值23。以此類推,如果是Double,底層就是調用的`doubleValue()`方法獲取數據值返回。
4. 常見操作
- 基本數據類型轉字符串:
- 靜態方法:toString(基本數據類型的數據值),例如:`String str = Integer.toString(23);`
- 推薦使用String的靜態方法:valueOf(基本數據類型的數據值),例如:`String str = String.valueOf(20);`
- 數值內容的字符串轉基本數據類型:
- 調用parseXXX的方法,例如:`int num = Integer.parseInt("66");`
- 注意:如果字符串不是數值內容,而是"a"、"b"、"中"...這樣的非數值,就會引發異常:NumberFormatException
5. 面試題
- 觀察以下代碼,說結果
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);
- 結果分別是:true,true,false,false
- 原因:
- Integer自動裝箱底層會調用valueOf()方法,源代碼:
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類的low屬性于high屬性做范圍判斷,其中low的值是-128,high的值是127
- 也就是說,調用valueOf()方法,會判斷數據是否在-128~127的范圍內。如果在范圍內,就從靜態內部類IntegerCache的一個cache數組屬性中獲取一個Integer對象
- 如果不在這個范圍內,就是新new一個Integer對象
- IntegerCache這個靜態內部類有一個靜態代碼塊:
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不會進入,所以high的值就被賦值127,經過計算,size變量的值就是256。
- 第二個if語句的條件通常是可以成立的,所以就創建了一個長度為256的Integer類型數組,通過一個for循環,給這個數組就從-128開始賦值,一致賦值到127結束,剛好是256個。
- 至此,內部類中就出現了一個Integer類型數組,緩沖了256個Integer對象,對應的數據范圍正好是:-128~127。
- 那么通過以上分析可知,只要是通過自動裝箱或者valueOf()方法去獲取對象,只要數據范圍在-128~127,不管獲取多少次,都會從數組中去拿緩沖的對象,所以拿到的始終是同一個,所以判斷的結果就是true。
- 但如果不在這個范圍內,就是去new一個新的Integer對象,會開辟一個新的對象空間,地址值肯定不一樣,所以結果就是false。