淺談java中BigDecimal的equals與compareTo的區(qū)別
這兩天在處理支付金額校驗(yàn)的時(shí)候出現(xiàn)了點(diǎn)問題,有個(gè)金額比較我用了BigDecimal的equals方法來比較兩個(gè)金額是否相等,結(jié)果導(dǎo)致金額比較出現(xiàn)錯(cuò)誤(比如3.0與3.00的比較等)。
【注:以下所講都是以sun jdk 1.4.2版本為例,其他版本實(shí)現(xiàn)未必一致,請(qǐng)忽略】
首先看一下BigDecimal的equals方法:
public boolean equals(Object x){ if (!(x instanceof BigDecimal)) return false; BigDecimal xDec = (BigDecimal) x; return scale == xDec.scale && intVal.equals(xDec.intVal); }
可以看到BigDecimal的euquals方法是先判斷要比較的數(shù)據(jù)類型,如果對(duì)象類型一致前提下同時(shí)判斷精確度(scale)和值(BigInteger的equals方法)是否一致。
其實(shí)javadoc里面就已經(jīng)寫的很明白:“Compares this BigDecimal with the specified Object for equality. Unlike compareTo, this method considers two BigDecimal objects equal only if they are equal in value and scale (thus 2.0 is not equal to 2.00 when compared by this method).”只是自己沒有去注意罷了!
再看一下compareTo方法:
public int compareTo(BigDecimal val){ /* Optimization: would run fine without the next three lines */ int sigDiff = signum() - val.signum(); if (sigDiff != 0) return (sigDiff > 0 ? 1 : -1); /* If signs match, scale and compare intVals */ BigDecimal arg[] = new BigDecimal[2]; arg[0] = this; arg[1] = val; matchScale(arg); return arg[0].intVal.compareTo(arg[1].intVal); }
可以看到這個(gè)方法里面有個(gè)matchScale的處理,意思是把精確度低的那個(gè)對(duì)象轉(zhuǎn)換為高精確度,然后再進(jìn)行比較(同樣是BigInteger的compareTo方法),matchScale的實(shí)現(xiàn)如下:
private static void matchScale(BigDecimal[] val) { if (val[0].scale < val[1].scale) val[0] = val[0].setScale(val[1].scale); else if (val[1].scale < val[0].scale) val[1] = val[1].setScale(val[0].scale); }
做個(gè)簡(jiǎn)單測(cè)試:
System.out.println(new BigDecimal("1.2").equals(new BigDecimal("1.20"))); //輸出false System.out.println(new BigDecimal("1.2").compareTo(new BigDecimal("1.20")) == 0); //輸出true
另外注意到我上面BigDecimal的構(gòu)造方法里面?zhèn)魅氲亩际亲址?,如果傳入的是?shù)字類型的話會(huì)有什么結(jié)果,大家可以自己測(cè)試一下,然后分析一下原因:
System.out.println(new BigDecimal("1.2").equals(new BigDecimal("1.20"))); //輸出false System.out.println(new BigDecimal("1.2").compareTo(new BigDecimal("1.20")) == 0); //輸出true System.out.println(new BigDecimal(1.2).equals(new BigDecimal("1.20"))); //輸出是? System.out.println(new BigDecimal(1.2).compareTo(new BigDecimal("1.20")) == 0); //輸出是? System.out.println(new BigDecimal(1.2).equals(new BigDecimal(1.20))); //輸出是? System.out.println(new BigDecimal(1.2).compareTo(new BigDecimal(1.20)) == 0);//輸出是?
最后結(jié)論是:對(duì)于BigDecimal的大小比較,用equals方法的話會(huì)不僅會(huì)比較值的大小,還會(huì)比較兩個(gè)對(duì)象的精確度,而compareTo方法則不會(huì)比較精確度,只比較數(shù)值的大小。
最后鄙視一下自己,用了這么多年的Java語言,連基本的常識(shí)都沒搞清楚!
以上這篇淺談java中BigDecimal的equals與compareTo的區(qū)別就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Java中BigDecimal比較大小的3種方法(??compareTo()、??equals()??和??compareTo()??)
- Java compareTo用法詳解
- JavaSE中compare、compareTo的區(qū)別
- Java 基礎(chǔ):string中的compareTo方法
- java compare compareTo方法區(qū)別詳解
- java compareTo和compare方法比較詳解
- java使用compareTo實(shí)現(xiàn)一個(gè)類的對(duì)象之間比較大小操作
- java中同類對(duì)象之間的compareTo()和compare()方法對(duì)比分析
- 詳解java中保持compareTo和equals同步
- Java中compareTo方法使用小結(jié)
相關(guān)文章
SpringBoot使用mybatis-plus分頁查詢無效的問題解決
MyBatis-Plus提供了很多便捷的功能,包括分頁查詢,本文主要介紹了SpringBoot使用mybatis-plus分頁查詢無效的問題解決,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12Java橋接模式實(shí)例詳解【簡(jiǎn)單版與升級(jí)版】
這篇文章主要介紹了Java橋接模式,結(jié)合實(shí)例形式分析了java橋接模式簡(jiǎn)單版與升級(jí)版兩種實(shí)現(xiàn)技巧,需要的朋友可以參考下2019-07-07java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件
這篇文章主要為大家詳細(xì)介紹了java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-05-05SpringBoot整合atomikos實(shí)現(xiàn)跨庫事務(wù)的詳細(xì)方案
這篇文章主要介紹了SpringBoot整合atomikos實(shí)現(xiàn)跨庫事務(wù),業(yè)務(wù)主要涉及政府及企業(yè)且并發(fā)量不大,所以采用XA事務(wù),雖然性能有所損失,但是可以保證數(shù)據(jù)的強(qiáng)一致性,需要的朋友可以參考下2022-06-06JAVA統(tǒng)計(jì)字符串中某個(gè)字符出現(xiàn)次數(shù)的方法實(shí)現(xiàn)
本文主要介紹了JAVA統(tǒng)計(jì)字符串中某個(gè)字符出現(xiàn)次數(shù)的方法實(shí)現(xiàn),可以循環(huán)使用String的charAt(int index)函數(shù),具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11