推荐使用 localdate.isleapyear() 判断闰年,它封装规则、线程安全;手写需满足 (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);必测 1900、2000、2100、2024 等边界值。

用 LocalDate.isLeapYear() 最省心
Java 8+ 推荐直接用 LocalDate.isLeapYear(),它封装了所有闰年规则,且线程安全、无需手动计算。传入年份即可,返回 boolean。
常见错误是自己写条件判断却漏掉“整百年必须被400整除”这条——比如把 1900 当成闰年。
-
LocalDate.isLeapYear(2000)→true(能被400整除) -
LocalDate.isLeapYear(1900)→false(能被100整除但不能被400整除) -
LocalDate.isLeapYear(2024)→true(能被4整除但不能被100整除)
手写判断逻辑时必须检查三个条件
如果因兼容性或教学需要手写,必须同时满足:能被4整除 且 (不能被100整除 或 能被400整除)。顺序和括号不能错,否则逻辑失效。
典型翻车场景:写成 year % 4 == 0 && year % 100 != 0 || year % 400 == 0 —— 因为 && 优先级高于 ||,等价于 (year % 4 == 0 && year % 100 != 0) || year % 400 == 0,看似对,但可读性差、易被误改。
立即学习“Java免费学习笔记(深入)”;
- 推荐写法:
(year % 4 == 0) && (year % 100 != 0 || year % 400 == 0) - 别用
if-else嵌套三层去判,既冗余又难维护 - 注意
year必须是正整数;负年份(如公元前)不适用该规则
别在 Calendar 或 Date 上绕弯子
Calendar 没有直接判断闰年的方法,有人试图用 getActualMaximum(Calendar.DAY_OF_YEAR) 看是不是366——这可行但低效,且依赖具体 TimeZone 和 Locale 设置,容易在跨时区服务中出偏差。
更糟的是用 new Date(year, 1, 29)(已废弃)再看日期是否被自动修正——Date 构造器会静默调整,无法可靠反推闰年。
-
Calendar方案性能差、可读性差、有隐藏时区依赖 -
Date构造器已标记为@Deprecated,JDK 17 后部分运行时可能抛警告 - 除非维护 JDK 6 项目,否则没必要碰这两者
测试边界年份比写逻辑更重要
闰年逻辑看着简单,但真实业务里最容易出问题的不是 2024,而是 1900、2000、2100 这类边界值。尤其涉及金融计息、合同期限、报表周期时,错一天就可能触发违约或审计异常。
- 必测年份:
1900(非闰年)、2000(闰年)、2100(非闰年)、2024(闰年) - 别只测当前年份或随机年份,边界值遗漏是回归缺陷主因
- 如果用
LocalDate.isLeapYear(),也要覆盖这些输入——它虽可靠,但调用方传错参数照样崩









