由BigDecimal引發的思考
本文綜合網上牛人以及Java API所寫,還有自己的一些專案經歷。主要實用工具Eclipse3.5、jdk1.6,測試框架JUnit4等。
float和double只能用來做科學計算或者是工程計算,在商業計算中我們要用java.math.BigDecimal。
-----《Effective Java》
看一個小例子:
測試結果:
讓人不可思議,怎麼會與自己的想象差的那麼遠!但,現實確實如此!
Java中的簡單浮點數型別float和double不能夠進行運算。不光是Java,在其它很多程式語言中也有這樣的問題。在大多數情況下,計算的結果是準確的,但是多試幾次(可以做一個迴圈)就可以試出類似上面的錯誤。
再者,Math類、DecimalFormat類有對應的處理資料的方法。例項程式碼:
顯示結果:
哎,還是讓人很失望。
難道在工程中,我們就這樣計算嗎?當然不是,Java還沒有“挫”,呵呵!下面談談BigDecimal。
BigDecimal有很多構造方法,詳看api文件。這裡主要說說下面兩個構造方法:
關於其他的構造方法,這裡不贅述,舉一反三吧!
這兩個構造方法,建議採用第二個,具體原因在api上解釋的很清楚。
翻譯一下:
使用BigDecimal,可以獲得交準確的計算結果,並且可以自己定義小數精度,具有一定的靈活性。例項程式碼:
其中,BigDecimal有很多常量欄位。ROUND_HALF_UP表示四捨五入。例項程式碼:
在JUnit4的幫助下,很好地完成了許多測試,解開了很多疑惑。如果你不明白最好還是多加測試。也許,你有更多的發現。
在好奇心的驅使下,又看看BigDecimal原始碼,主要涉及到其valueOf(double val)方法,該方法是靜態方法,原始碼如下:
可以看出,valueOf(double val)方法以BigDecimal(Double.toString(val))方式返回一個BigDecimal物件。所以在以double為源的時候創
建BigDecimal物件,可以採用該方法。修改上面例項程式碼如下:
在看原始碼的時候,經常看到別人使用valueof**方法,難道它有什麼與眾不同嗎?研究一下ing.....
首先,研究一下Integer的建立方式:
根據註釋來看,equals比較之後都是true,這很好理解。因為Integer重寫了equals方法,只要內容相同,equals比較就是true。再者new方式產出的物件用”=“比較肯定是false,但是為什麼同樣是valueOf,一個是true,而另一個卻是false???!!!
不要急,看看Integer原始碼:
IntegerCache是靜態內部類。從原始碼可以看出使用valueOf方法建立Integer例項時:
當這個值在-128和127之間時,會用快取儲存起來,供多次使用,以節約記憶體。
如果不在這個範圍內,則建立一個新的Integer物件。 再看一個例項:
暈。。居然false,why????
反編譯一下這段程式碼,看看它神祕的面紗。
哦,原來如此。自動裝箱使用的就是valueOf方法,額的神啊!那麼自動拆箱是什麼原理?
另外,算是提示吧?!
初始化一個字串, String s1 = "s1"; 這樣的程式碼肯定比 String s2 = new String("s2");程式碼強,將其他型別的值轉換成String的時候,valueof方法比new方法效率也高。
文章到此為止,希望對你有用!
非常感謝:
這篇文章引用了他們的某些程式碼片段,如果不是他們的無私奉獻,估計我沒有勇氣和能力寫出這篇文章,再次感謝他們,向他們學習!!!