最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

因BigDecimal類型數(shù)據(jù)引出的問題詳析

 更新時間:2018年08月19日 14:23:13   作者:lensar  
Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數(shù)進(jìn)行精確的運算,下面這篇文章主要給大家介紹了因BigDecimal類型數(shù)據(jù)引出的問題的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

我們都知道,java中對大小數(shù),高精度的計算都會用到BigDecimal.但是在實際應(yīng)用中,運用BigDecimal還是會遇到一些問題,下面話不多說了,來一起看看詳細(xì)的介紹吧

問題描述:

程序中需要判斷一個字段是否為0(字段類型為BigDecimal),想都沒想,對象的判斷用equals?結(jié)果卻與預(yù)期有一定的差距,看下面代碼及運行結(jié)果。

 public static void main(String[] args) {
  BigDecimal decimal1 = BigDecimal.valueOf(0);
  BigDecimal decimal2 = new BigDecimal("0.00");
  System.out.println("the result is " +decimal1.equals(decimal2));
 }

運行結(jié)果:

the result is false

結(jié)論: BigDecimal類型比較相等不能簡單的通過equals方法實現(xiàn)。

BigDecimal類的equals方法源碼如下:

 public boolean equals(Object x) {
  if (!(x instanceof BigDecimal))
   return false;
  BigDecimal xDec = (BigDecimal) x;
  if (x == this)
   return true;
  if (scale != xDec.scale)//這里會比較數(shù)字的精度
   return false;
  long s = this.intCompact;
  long xs = xDec.intCompact;
  if (s != INFLATED) {
   if (xs == INFLATED)
    xs = compactValFor(xDec.intVal);
   return xs == s;
  } else if (xs != INFLATED)
   return xs == compactValFor(this.intVal);

  return this.inflate().equals(xDec.inflate());
 }

看上面的注釋可以知道,BigDecimal類的equals方法會判斷數(shù)字的精度,看下面的代碼及運行結(jié)果:

 public static void main(String[] args) {
  BigDecimal decimal1 = BigDecimal.valueOf(0).setScale(2);
  BigDecimal decimal2 = new BigDecimal("0.00").setScale(2);
  System.out.println("the result is " +decimal1.equals(decimal2));
 }

運行結(jié)果:

the result is true

結(jié)論: 使用BigDecimal類equals方法判斷兩個BigDecimal類型的數(shù)據(jù)時,需要設(shè)置精度,否則結(jié)果可能不正確。

思考:每次都設(shè)置精度比較麻煩,有其他方式進(jìn)行相等的比較嗎?

看了下BigDecimal的方法列表,有一個名為compareTo的方法,通過注釋可知,貌似可以進(jìn)行不同精度的比較,看下面的代碼。

 public static void main(String[] args) {
  BigDecimal decimal1 = BigDecimal.valueOf(1.1);
  BigDecimal decimal2 = new BigDecimal("1.10");
  System.out.println("the result is " +decimal1.compareTo(decimal2));
 }

運行結(jié)果:

the result is 0

0表示兩個數(shù)相等,所有可以通過compareTo實現(xiàn)不同精度的兩個BigDecimal類型的數(shù)字是否相等的比較

引出的問題:公司的項目中,為了避免由于精度丟失引起問題,凡是有精度要求的字段用的都是BigDecimal類型。數(shù)據(jù)持久層用的是Mybatis框架,Mybatis的mapper文件中有些條件判斷用的是BigDecimal對應(yīng)的字段,如下:

<select id="selectByCondition" resultType="com.scove.demo.domain.Score">
 select * from tb_score where 1=1 
 <if test="score!=null and score!=0">
  and score&gt;#{score}
 </if>
 ...

score是一個BigDecimal類型的字段,score!=0 Mybatis是如何進(jìn)行判斷的,會不會用的是上面的equals方法?如果是那么項目上線會不會捅大簍子,想到這兒,有點怕了。寫了個程序測了下,這樣寫完全沒問題,能夠達(dá)到我想要的目的。但是還是有點擔(dān)心,看看Mybatis底層是如何實現(xiàn)的吧,以免以后犯類似的錯誤嘛。

經(jīng)過分析調(diào)試,很快就找到了關(guān)鍵代碼的位置,如下:

public class ExpressionEvaluator {

 public boolean evaluateBoolean(String expression, Object parameterObject) {
 Object value = OgnlCache.getValue(expression, parameterObject);
 if (value instanceof Boolean) {
  return (Boolean) value;
 }
 if (value instanceof Number) {
  return !new BigDecimal(String.valueOf(value)).equals(BigDecimal.ZERO);
 }
 return value != null;
 }
...
public final class OgnlCache {

....
 public static Object getValue(String expression, Object root) {
 try {
  Map<Object, OgnlClassResolver> context = Ognl.createDefaultContext(root, new OgnlClassResolver());
  return Ognl.getValue(parseExpression(expression), context, root);
 } catch (OgnlException e) {
  throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e);
 }
 }

用的是表達(dá)式求值,Ognl這個類的竟然沒有源碼,apache的官網(wǎng)上找了下,是有相應(yīng)的源碼的,只是需要單獨下載,真麻煩,算了不看了。據(jù)說底層用的是Spring 的ognl表達(dá)式,我也不 關(guān)心了。但是以后如果不確定mapper中的test是否正確咋個辦?

想了下,還是寫一個工具類在拿不準(zhǔn)的時候用一下吧,反正拿不準(zhǔn)的時候肯定很少,所以隨便寫了簡單的吧,如下:

 public static void main(String[] args) {
  ExpressionEvaluator evaluator = new ExpressionEvaluator();
  String expression = "score!=null and score!=0";
  DynamicContext context = new DynamicContext(new Configuration(), null);
  context.bind("score", BigDecimal.valueOf(0.1));
  Boolean flag = evaluator.evaluateBoolean(expression , context.getBindings());
  System.out.println("the result is " +flag);
 }

運行結(jié)果:

the result is true

總結(jié)

開發(fā)過程中,一定要細(xì)心去處理細(xì)節(jié)上的東西,不然一不小心就跳坑里了,輕則系統(tǒng)造成數(shù)據(jù)的不一致,修復(fù)數(shù)據(jù);重則造成重大的損失....

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Java開源工具iText生成PDF簡單實例

    Java開源工具iText生成PDF簡單實例

    這篇文章主要介紹了Java開源工具iText生成PDF簡單實例,本文給出了3段代碼實例,講解創(chuàng)建一個簡單PDF文件,在PDF中添加表格以及在PDF中添加圖片,需要的朋友可以參考下
    2015-07-07
  • Java中json使用方法_動力節(jié)點Java學(xué)院整理

    Java中json使用方法_動力節(jié)點Java學(xué)院整理

    JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式, json是個非常重要的數(shù)據(jù)結(jié)構(gòu),在web開發(fā)中應(yīng)用十分廣泛。下面通過本文給大家講解Java中json使用方法,感興趣的朋友一起看看吧
    2017-07-07
  • Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    Springboot整合JPA配置多數(shù)據(jù)源流程詳解

    這篇文章主要介紹了Springboot整合JPA配置多數(shù)據(jù)源,JPA可以通過實體類生成數(shù)據(jù)庫的表,同時自帶很多增刪改查方法,大部分sql語句不需要我們自己寫,配置完成后直接調(diào)用方法即可,很方便
    2022-11-11
  • idea創(chuàng)建spring?boot項目時javaversion只能選擇17和21解決辦法

    idea創(chuàng)建spring?boot項目時javaversion只能選擇17和21解決辦法

    這篇文章主要給大家介紹了關(guān)于idea創(chuàng)建spring?boot項目時javaversion只能選擇17和21的解決辦法,文中通過代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-01-01
  • 詳解JAVA 反射機(jī)制

    詳解JAVA 反射機(jī)制

    這篇文章主要介紹了JAVA 反射機(jī)制的相關(guān)知識,文中講解的非常細(xì)致,代碼幫助大家更好的理解學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • Java多線程之synchronized關(guān)鍵字的使用

    Java多線程之synchronized關(guān)鍵字的使用

    這篇文章主要介紹了Java多線程之synchronized關(guān)鍵字的使用,文中有非常詳細(xì)的代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • Java有效處理異常的三個原則

    Java有效處理異常的三個原則

    Java中異常提供了一種識別及響應(yīng)錯誤情況的一致性機(jī)制,有效地異常處理能使程序更加健壯、易于調(diào)試。那么這篇文章總結(jié)了Java有效處理異常的三個原則,有需要的朋友們可以參考借鑒。
    2016-09-09
  • java實現(xiàn)的RSA加密算法詳解

    java實現(xiàn)的RSA加密算法詳解

    這篇文章主要介紹了java實現(xiàn)的RSA加密算法,結(jié)合實例形式詳細(xì)分析了RSA加密解密的原理、java實現(xiàn)方法及相關(guān)注意事項,需要的朋友可以參考下
    2017-06-06
  • Java常見啟動命令-jar、-server和-cp詳細(xì)比較

    Java常見啟動命令-jar、-server和-cp詳細(xì)比較

    這篇文章主要給大家介紹了關(guān)于Java常見啟動命令-jar、-server和-cp詳細(xì)比較的相關(guān)資料,該文總結(jié)了常歸的jar包的啟動方式,并分析各種啟動方式的區(qū)別,需要的朋友可以參考下
    2023-07-07
  • java HashMap,TreeMap與LinkedHashMap的詳解

    java HashMap,TreeMap與LinkedHashMap的詳解

    這篇文章主要介紹了 java HashMap,TreeMap與LinkedHashMap的詳解的相關(guān)資料,這里提供實例代碼,幫助大家學(xué)習(xí)理解 這部分的內(nèi)容,需要的朋友可以參考下
    2016-11-11

最新評論

大方县| 惠来县| 海林市| 嘉兴市| 永德县| 法库县| 乌兰浩特市| 乌海市| 都安| 建昌县| 农安县| 三河市| 吉林省| 乡宁县| 洛隆县| 常德市| 任丘市| 阜新市| 墨脱县| 邳州市| 尼玛县| 黑山县| 南溪县| 赤峰市| 荥阳市| 崇仁县| 六枝特区| 岳池县| 灯塔市| 凤冈县| 克山县| 福清市| 古丈县| 城口县| 龙里县| 徐州市| 固镇县| 台山市| 蓬溪县| 大英县| 双流县|