在面試過程中,常常會有面試官問到基礎的問題的時候都會問到Java的拆裝箱,關于這個問題其實不是很難,但是如果平時進行自學的時候不是注意,就可能一臉懵逼,所以筆者就這個問題進行一些總結,共同促進!
一、拆裝箱概念
所謂的拆裝箱,就是自從JDK1.5之后,java的基本類型和引用類型之間的相互轉換。
1.1拆箱
拆箱就是把Long,Integer,Double,Float 等將基本數據類型的首字母大寫的相應的引用類型轉化為基本數據類型的動作就叫拆箱。
1.2裝箱
裝箱就是把byte ,int ,short, long ,double,float,boolean,char 這些Java的基本數據類型在定義數據類型時不聲明為相對應的引用類型,在編譯器的處理下自動轉化為引用類型的動作就叫做裝箱。
二、拆裝箱的相關應用
在JDK1.5后,當我們進行基本類型和引用類型的轉換的時候就會方便:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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(); } } |
上面介紹了關于拆裝箱的一些基本點和使用方式,但是要使用拆裝箱的話還有一些注意點需要注意,下面將這些注意點進行一些總結。
三、注意點
首先貼一段代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
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類的源碼,從源碼的角度來分析這個問題:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
/** * 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可以體現出來,源碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
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為例子,貼出代碼討論:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
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方法來討論,貼出源碼就一目了然了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/** * 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,就不過多贅述了。
以上就是筆者對于拆裝箱的一些整理,如果讀者有不同的看法可以在評論區提出,筆者再進行修改!
希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/Java766357768/p/7648516.html