clojure.java-time解析字符串为日期时特定函数调用出现空指针异常
异常诱因
从栈顶java.lang.Class/isAssignableFrom抛出空指针可以直接定位根因:java-time库做输入类型检查时,拿到的输入值为nil,调用class方法取nil的类型返回null,触发了空指针异常。
你观察到打印time2能得到合法时间格式,有三种常见的实际场景:
- 你只检查了第二个入参
time-last-similar,但第一个入参time实际为nil similar-transactions过滤结果为空时,(first similar-transactions)返回nil,你打印的是其他正常分支的日志,不是报错那次的入参- 少数情况:你传入的时间值是延迟求值对象(比如未取值的delay、懒序列元素),打印时触发求值得到了合法值,但
time/instant解析时没有对应处理逻辑,内部取值得到nil
另外你编写的doubled-transaction?本身存在逻辑漏洞:没有匹配的相似交易时,time-last-similar必然是nil,直接传给时间差计算函数一定会触发报错。
解决方法
- 优先加空值防护,在调用时间差函数前判断所有入参非空,同时处理无相似交易的边界情况:
(defn doubled-transaction? [merchant amount time transactions] ;; 前置校验必要入参非空 (when (and time (seq transactions)) (let [similar-transactions (filter (has-values :merchant merchant :amount amount) transactions) time-last-similar (:time (first similar-transactions))] ;; 存在相似交易再做时间差判断 (when time-last-similar (< (calculate-time-diff time time-last-similar) 120)))))
- 如果存在延迟求值的时间值,可在
calculate-time-diff内部加强制取值和空值校验:
(defn calculate-time-diff [time1 time2] ;; 前置断言入参非空,提前暴露问题 {:pre [(some? time1) (some? time2)]} (let [;; force兼容普通值和延迟求值对象 parsed-time1 (time/instant (force time1)) parsed-time2 (time/instant (force time2))] (time/time-between parsed-time1 parsed-time2 :seconds)))
- 如果排查确认入参非空仍报错,就是
java-time识别不了入参的时间类型,可显式转成字符串再解析:
(time/instant (str time-val))
内容的提问来源于stack exchange,提问作者brenobarreto
相关产品推荐
相关产品推荐

