java:基本類型優先於裝箱基本類型

Java有一個類型系統是由兩部分組成,包含基本類型,如int,double等,它對應的引用類型,稱之為裝箱基本類型,如int對應的Integer。Java1.5發行版本中增加了自動裝箱和自動拆箱。

在基本類型和裝箱類型之間有三個主要區別。第一,基本類型只有值,而裝箱類型不只有值,還可以創建對象。第二,裝箱類型可以是null,基本類型不行。最後一點,基本類型更節省時間和空間。這三點區別有可能會讓我們陷入麻煩之中,如下代碼:

這個比較器表面看還不錯,但如果列印naturalOrder.compare(new Integer(42,new Integer(42)))的值,卻並不是我們認為的0,而是輸出1。問題在哪裡呢,修正這個問題的方法,就是定義兩個局部變數,用來保存對應first和second的基本類型,如下:

Advertisements

這樣列印出來就是0了,相信大家都明白了,對裝箱類型運用「==」的操作符總是錯誤的,所以才會返回1,因為它們是對象,不是單純的值。

接下來,考慮這個小程序

它也不列印出Unbelievable,而是拋出NullPointerException異常,問題在於,i是Integer,而不是int,就像所有的對象引用域一樣,它的初始值是null,當程序計算表達式i==42時,它就會將Integer與int比較,這時候它會自動拆箱,但是null對象自動拆箱,就會報空指針異常。修正這個問題也很簡單,聲明i是int類型而不是Integer類型就行。

最後,再考慮一下這個程序:

這個程序運行會慢一點,因為它將一個局部變數sum聲明為裝箱類型,而不是基本類型long,程序本身不會錯,只是它反覆的裝箱和拆箱,導致性能降低。

Advertisements

那麼什麼時候用裝箱類型呢,第一個就是作為集合中的元素、鍵和值。你不能將基本類型放到集合中,因此只能使用裝箱類型。第二在參數化類型中,必須使用裝箱基本類型作為類型參數,因為java不允許使用基本類型,例如,你不能將變數聲明為ThreadLocal<int>類型,只能使用ThreadLocal<Integer>替代。最後,在進行反射的方法調用時,必須使用裝箱基本類型。

Advertisements

你可能會喜歡