Java开发中最容易忽略哪些异常

Java开发中最容易忽略哪些异常 在Java开发中最容易被忽视的不是编译错误而是那些“看似无害”但在运行过程中悄然崩溃、数据混乱或资源泄漏的隐藏异常——它们不会打断编译不会显式抛出甚至很难在日志中找到。空指针异常NullPointerException的隐形温床很多人以为加了if (obj ! null)事实上隐患往往隐藏在链式调用、自动拆箱、集合取值、Optional误用等场景中。例如user.getAddress().getCity().toUpperCase()中间任何一个环节都是null会炸的再比如Integer id map.get(id); int value id.intValue();当map没有这个key时返回null拆箱即NPE。用Objects.requireNonNull()主动拦截关键入参处链式调用改用Optional.ofNullable(obj).map(...).orElse(...)优先使用Map取值getOrDefault(key, defaultValue)避免null返回“启用IDEA”Nullability annotations”Nullable/NonNull并开始编译期检查资源未关闭导致泄漏异常IO流、如果只依赖数据库连接、HTTP客户端、线程池等资源finally手动close很容易因为异常而跳过关闭逻辑而try-with-resources虽然好但只适用于实现AutoCloseable许多自定义资源或旧框架API不支持。所有实现AutoCloseable必须使用try的资源-with-resources禁用裸try-finally自定义资源类必须正确实现close()并在Javadoc中标明是否功等使用Apache Commons IO或Guava工具(如IOUtils.closeQuietly()处理非标准资源在单元测试中使用System.gc()Thread.sleep() 日志观察资源释放(辅助验证)并发场景中的“幽灵异常”ConcurrentModificationException、IllegalMonitorStateException、死锁ABA问题...这些并不总是异常抛售但一旦触发往往伴随着偶然、难以复制和缺乏日志。比如遍历Arraylist同时被另一行修改synchronized锁对象意外变更或者使用比较volatile引用会导致可见性误判。集合优先使用遍历CopyOnWriteArrayList或ConcurrentHashMap而不是同步包装synchronized块锁的对象必须是privatetee final和稳定的生命周期(避免使用string)、Integer等可变/共享对象)优先考虑多线程共享状态AtomicInteger、StampedLock或ReentrantLock取代synchronizeded代替synchronided自带JDKjstack或者Arthas实时dump线程栈排除阻塞和锁竞争由日期和时间区域引起的沉默错误SimpleDateFormat非线程安全Date毫秒值被误当秒处理LocalDateTime无时区信息参与跨系统时间计算Calendar月份从0开始...这些不会抛出异常但偏差几个小时甚至几天。上线后发现订单加班报告不对。全局禁用SimpleDateFormat统一用DateTimeFormatter(不可变线程安全)存储所有时间Instant或带时区的ZonedDateTime避免LocalDateTime单独落库强制约定前端和后端之间的时间交互 8601格式如2024-05-20T13:45:00Z分析服务端时ZoneID明确指定单元测试涵盖夏令切换、跨年、跨月等边界时间点基本上就是这些——不是冷门知识而是每天在编写的代码中反复踩坑的“熟面孔”。虽然不复杂但很容易被忽视