Java Calendar set()方法陷阱解析与解决方案

5星 · 超过95%的资源 3 下载量 138 浏览量 更新于2024-09-09 收藏 418KB PDF 举报
"解决Java Calendar类set()方法的陷阱" 在Java编程中,`Calendar`类是用于处理日期和时间的重要工具。然而,由于其内部的工作机制,开发者在使用`set()`方法时可能会遇到一些陷阱。本文将深入探讨这个问题,并提供解决方案。 首先,`Calendar`类的`set()`方法允许我们设置日期和时间的各种组件,如年、月、日、小时等。然而,当我们单独设置月份时,需要注意的是,`Calendar`类的月份是从0开始的,1月对应0,2月对应1,以此类推,12月对应11。因此,当我们在调用`set(Calendar.MONTH, month-1)`时,如果传入的`month`是9,实际上它会设置为8,即8月。 在给出的示例代码中,我们尝试获取2017年9月的最后一天。首先,创建了一个`Calendar`实例,然后设置了年份为2017,接着设置月份为`month-1`,也就是8。接着,通过`getActualMaximum(Calendar.DAY_OF_MONTH)`获取9月的最大日期,即30。然后,将这个最大日期设置回去,期望得到2017年9月30日。然而,问题出在了这里。 当我们将`DAY_OF_MONTH`设置为30后,`Calendar`类会自动调整日期以保持其有效性和连续性。在这个例子中,由于9月有30天,将`DAY_OF_MONTH`设置为30是正确的。然而,问题出现在10月31日这一天,因为10月有31天。当我们在10月31日运行这段代码,且传入的`month`参数为9时,`Calendar`会将月份设置为8(代表9月),然后将`DAY_OF_MONTH`设置为30。此时,`Calendar`会自动把日期调整到下个月的第一天,因为9月没有31日,所以结果变成了10月1日。 为了解决这个问题,我们需要在设置月份之后,再次检查并设置日期,确保它不会跨越到下个月。下面是修正后的代码: ```java import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class TestCalendar { public static void main(String[] args) { String s = new SimpleDateFormat("yyyy-MM-dd") .format(getLastDay(2017, 9)); System.out.println(s); } public static Date getLastDay(int year, int month) { // 获取Calendar类的实例 Calendar c = Calendar.getInstance(); // 设置年份 c.set(Calendar.YEAR, year); // 设置月份,注意月份从0开始 c.set(Calendar.MONTH, month - 1); // 获取当前时间下,该月的最大日期的数字 int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH); // 在设置最大日期前,先清除现有的日期 c.clear(Calendar.DAY_OF_MONTH); // 将获取的最大日期数设置为Calendar实例的日期数 c.set(Calendar.DAY_OF_MONTH, lastDay); return c.getTime(); } } ``` 在这个修正后的版本中,我们在设置`DAY_OF_MONTH`之前清除了现有日期,这样可以避免`Calendar`自动调整到下个月的情况。现在,即使在10月31日运行这段代码,也可以正确地返回2017年9月30日。 理解`Calendar`类的内部行为是避免此类陷阱的关键。在使用`set()`方法时,尤其是涉及到月份和日期的交互时,要特别注意日期的自动调整,确保在设置日期前清除不必要的字段,以防止意外的日期跳变。同时,对于涉及月份的计算,记住月份是从0开始的,这能帮助我们正确地设置`Calendar`对象。