事出有因
在最近準備安卓面試的過程中,一位資深的大神問了我關于裝箱和拆箱的一些知識點。無奈小弟平時沒怎麼關注這個方面的知識點,拿來就是用,完全沒有沒有考慮到使用上的性能損耗和一些注意事項問題。是以經曆此面試之後,決定好好複習一下關于這方面的知識點,并總結出這篇文章,供自己日後快速複習,同時也希望本篇文章能給各位看官帶來收益。
例子1
· 知識點
1 自動裝箱 & 自動拆箱
2 比較符“==”和“equal”,在使用上的注意事項
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 220;
Integer f = 220;
Long g = 3L;
System.out.println(c == d);
System.out.println(e == f);
System.out.println(c == (a + b));
System.out.println(c.equals(a + b));
System.out.println(g == (a + b));
System.out.println(g.equals(a + b));
}
複制代碼
小夥伴們先猜想上面程式輸出的結果,認真的思考一下。
· 解釋
在程式中變量:a,b,c,d,e,f,g都是對基本資料包裝類,在初始化這些變量的時候,實際上java編譯器幫我們使用裝箱來指派。例如:Integer a = 1; 編譯後換算成 Integer a = Integer.valueOf(1); 這個過程就被稱為裝箱啦,需要注意一點的是變量a為Integer對象類型,為實際儲存值的位址引用。
當列印:c == d的時候,此時兩者的對象類型都是Integer,那麼此時比較的是兩者的位址引用。此處的結果傳回為true,那麼我們能間接得出結論:c和d都指向同一個對象,指向的對象值為3
當列印:e == f的時候,同樣的此時兩者的對象類型都是Integer,那麼此時比較的是兩者的位址引用。但是此處傳回的結果為false,那麼我們能間接得出結論:e和f指向不同的對象,但是對象的值都為220。
對比上面兩條結果,我們是否有疑問。為啥第一條列印為true,第二條列印為false。想要搞懂這其中的原因,那麼就需要知道Integer中的Cache的概念,下面貼出其中的源碼:
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() {}
}
複制代碼
上面的源碼不是特别複雜,各位看官可以先大緻觀摩一下,再來看我的解析,了解起來能夠事半功倍。
源碼解析:IntegerCache是Integer的靜态内部類,用來緩存Integer對象。使用數組的形式來緩存,并且數組的大小為256,緩存值的範圍為:[-128 ,127]。如果值的取值範圍沒有在這個區間中,那麼這個對象将不會儲存
結論:值為3的Integer對象,會儲存在緩存中。值為220,不在儲存的區間範圍内,是以每次都是建立新的Integer類型對象
當列印“c == (a+b)” 的時候,結果為true。為什麼為true?
我來解析一下這個過程:
a+b等同于a.value+b.value , 其中a.value = 1,b.value = 2 ,是以:a+b的結果為基本類型3(這個過程就是拆箱的過程,一般在遇到算數運算符的時候,包裝類型就是自動拆箱)“c == (a+B)” 就等同于 “c == 3”,因為此時的c的類型為Integer,是以需要拆箱比較,最終的比較形式為:c.value == 3
當列印“c.equals(a+b)”的時候,結果也為true
和上面一樣,解析一下過程:a+b的解析和上面一樣。我們重點來看"c.equals(a+b)",Integer.equals()方法需要傳入Object對象,那麼a+b需要裝箱變為Integer對象。程式就變成“c.equals(Integer.value(3))”,是以結果為true
注意事項:包裝類的裝箱和拆箱涉及到性能損耗,因為程式需要多執行幾步。涉及到基本算術運算符,就會涉及到拆箱,變量初始化涉及到裝箱
當列印“g == (a + b)”,因為(a+b)得到結果為基本類型3。變量g的類型為Long,當執行g == 3的時候需要拆箱變成3 == 3 。是以得到的結果為true。
當列印“g.equals(a + b),結果為false。為什麼結果不是true,因為:g的類型為Long,那麼Long.equals()方法比較的對象類型也需要為Long,源碼如下:
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
複制代碼
因為a+b得到的結果為整型3,是以程式變成g.equals(Integer.valueOf(3)),可以看到兩者對象的類型都不相同,盡管他們的值都為3,但程式結果還是傳回false
注意事項:當使用不同包裝類的equals方法時候,需要注意比較的類型不同結果直接傳回false
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iN1EWZxEmY1MTZjRTYhBzY5QmN0MWNiJmN0MWZ5MzNi9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
關于找一找教程網
本站文章僅代表作者觀點,不代表本站立場,所有文章非營利性免費分享。
本站提供了軟體程式設計、網站開發技術、伺服器運維、人工智能等等IT技術文章,希望廣大程式員努力學習,讓我們用科技改變世界。
[有關Java包裝類的自動裝箱和拆箱--使用注意事項]http://www.zyiz.net/tech/detail-128900.html