最新公告
  • 欢迎光临数据科学与编程,我们是数据学科学兴趣交流小组立即加入我们
  • Java日常开发的21个坑,你入坑了嘛?

    前言

    最近看了极客时间的《Java业务开发常见错误100例》,再结合平时踩的一些代码坑,写写总结,希望对大家有帮助,感谢阅读~

    1. 六类典型空指针问题

    • 包装类型的空指针问题
    • 级联调用的空指针问题
    • Equals方法左边的空指针问题
    • ConcurrentHashMap 这样的容器不支持 Key 和 Value 为 null。
    • 集合,数组直接获取元素
    • 对象直接获取属性

    2. 日期YYYY格式设置的坑

    日常开发,经常需要对日期格式化,但是呢,年份设置为YYYY大写的时候,是有坑的哦。

    为什么明明是2019年12月31号,就转了一下格式,就变成了2020年12月31号了?因为YYYY是基于周来计算年的,它指向当天所在周属于的年份,一周从周日开始算起,周六结束,只要本周跨年,那么这一周就算下一年的了。正确姿势是使用yyyy格式。



    3.金额数值计算精度的坑

    可以发现,结算结果跟我们预期不一致,其实是因为计算机是以二进制存储数值的,对于浮点数也是。对于计算机而言,0.1无法精确表达,这就是为什么浮点数会导致精确度缺失的。因此,「金额计算,一般都是用BigDecimal 类型」

    在进行金额计算,使用BigDecimal的时候,我们还需要「注意BigDecimal的几位小数点,还有它的八种舍入模式哈」

    4. FileReader默认编码导致乱码问题

    从运行结果,可以知道,系统默认编码是utf8,demo中读取出来,出现乱码了。为什么呢?

    FileReader 是以当「前机器的默认字符集」来读取文件的,如果希望指定字符集的话,需要直接使用 InputStreamReader 和 FileInputStream。

    可以发现,i在一定范围内,是会返回缓存的。

    默认情况下呢,这个缓存区间就是[-128, 127],所以我们业务日常开发中,如果涉及Integer值的比较,需要注意这个坑哈。还有呢,设置 JVM 参数加上 -XX:AutoBoxCacheMax=1000,是可以调整这个区间参数的,大家可以自己试一下哈

    6. static静态变量依赖spring实例化变量,可能导致初始化出错

    7. 使用ThreadLocal,线程重用导致信息错乱的坑

    按理说,每次获取的before应该都是null,但是呢,程序运行在 Tomcat 中,执行程序的线程是 Tomcat 的工作线程,而 Tomcat 的工作线程是基于线程池的。

    线程池会重用固定的几个线程,一旦线程重用,那么很可能首次从 ThreadLocal 获取的值是之前其他用户的请求遗留的值。这时,ThreadLocal 中的用户信息就是其他用户的信息。

     

    用户1,请求过来,会有以下结果,符合预期:

    用户2请求过来,会有以下结果,「不符合预期」



     

    8. 疏忽switch的return和break

     

     

    9. Arrays.asList的几个坑

    10. ArrayList.toArray() 强转的坑

    11. 异常使用的几个坑

    11.1 不要弄丢了你的堆栈异常信息

    12.JSON序列化,Long类型被转成Integer类型!

    「注意啦」,序列化为Json串后,Josn串是没有Long类型呢。而且反序列化回来如果也是Object接收,数字小于Interger最大值的话,给转成Integer啦!

    13. 使用Executors声明线程池,newFixedThreadPool的OOM问题

    「IDE指定JVM参数:-Xmx8m -Xms8m :」

    运行结果:

     

    newFixedThreadPool线程池的核心线程数是固定的,它使用了近乎于无界的LinkedBlockingQueue阻塞队列。当核心线程用完后,任务会入队到阻塞队列,如果任务执行的时间比较长,没有释放,会导致越来越多的任务堆积到阻塞队列,最后导致机器的内存使用不停的飙升,造成JVM OOM。

    14. 直接大文件或者一次性从数据库读取太多数据到内存,可能导致OOM问题

    如果一次性把大文件或者数据库太多数据达到内存,是会导致OOM的。所以,为什么查询DB数据库,一般都建议分批。

    如果是太大的文件,可以使用Files.line()按需读取,当时读取文件这些,一般是使用完需要「关闭资源流」的哈

    15. 先查询,再更新/删除的并发一致性问题

    16. 数据库使用utf-8存储, 插入表情异常的坑

    低版本的MySQL支持的utf8编码,最大字符长度为 3 字节,但是呢,存储表情需要4个字节,因此如果用utf8存储表情的话,会报SQLException: Incorrect string value: 'xF0x9Fx98x84' for column,所以一般用utf8mb4编码去存储表情。

    17. 事务未生效的坑

    日常业务开发中,我们经常跟事务打交道,「事务失效」主要有以下几个场景:

    • 底层数据库引擎不支持事务
    • 在非public修饰的方法使用
    • rollbackFor属性设置错误
    • 本类方法直接调用
    • 异常被try…catch吃了,导致事务失效。

       

    18. 当反射遇到方法重载的坑

    19. mysql 时间 timestamp的坑

     

    我们可以发现 「c列」 是有CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,所以c列会随着记录更新而「更新为当前时间」。但是b列也会随着有记录更新为而「更新为当前时间」

    可以使用datetime代替它,需要更新为当前时间,就把now()赋值进来,或者修改mysql的这个参数explicit_defaults_for_timestamp

    20. mysql8数据库的时区坑

    之前我们对mysql数据库进行升级,新版本为8.0.12。但是升级完之后,发现now()函数,获取到的时间比北京时间晚8小时,原来是因为mysql8默认为美国那边的时间,需要指定下时区


    本站上原创文章未经作者许可,不得用于商业用途,仅做学习交流使用,本站免责声明。转载请注明出处,否则保留追究法律责任的权利。《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权
    数据科学与编程 » Java日常开发的21个坑,你入坑了嘛?

    发表评论

    • 52会员总数(位)
    • 310资源总数(个)
    • 32本周发布(个)
    • 1 今日发布(个)
    • 331稳定运行(天)

    提供最优质的博文资源集合

    立即阅览 了解详情