set(f, value) 将日历字段 f 更改成 value。此外,它设置了一个内部成员变量,以指示日历字段 f 已经被更改。尽管日历字段 f 是当即更改的,可是直到下次调用 get()、getTime()、getTimeInMillis()、add() 或 roll() 时才会从新计算日历的时间值(以毫秒为单位)。所以,屡次调用 set() 不会触发屡次没必要要的计算。使用 set() 更改日历字段的结果是,其余日历字段也可能发生更改,这取决于日历字段、日历字段值和日历系统。此外,在从新计算日历字段以后,get(f) 不必经过调用 set 方法返回 value 集合。具体细节是经过具体的日历类肯定的。 示例:假定 GregorianCalendar 最初被设置为 1999 年 8 月 31 日。调用 set(Calendar.MONTH, Calendar.SEPTEMBER) 将该日期设置为 1999 年 9 月 31 日。若是随后调用 getTime(),那么这是解析 1999 年 10 月 1 日的一个暂时内部表示。可是,在调用 getTime() 以前调用 set(Calendar.DAY_OF_MONTH, 30) 会将该日期设置为 1999 年 9 月 30 日,由于在调用 set() 以后没有发生从新计算。//set不会当即从新计算日历的毫秒偏移量和其它全部字段 add(f, delta) 将 delta 添加到 f 字段中。这等同于调用 set(f, get(f) + delta),但要带如下两个调整: Add 规则 1。调用后 f 字段的值减去调用前 f 字段的值等于 delta,以字段 f 中发生的任何溢出为模。溢出发生在字段值超出其范围时,结果,下一个更大的字段会递增或递减,并将字段值调整回其范围内。 Add 规则 2。若是指望某一个更小的字段是不变的,但让它等于之前的值是不可能的,由于在字段 f 发生更改以后,或者在出现其余约束以后,好比时区偏移量发生更改,它的最大值和最小值也在发生更改,而后它的值被调整为尽可能接近于所指望的值。更小的字段表示一个更小的时间单元。HOUR 是一个比 DAY_OF_MONTH 小的字段。对于不指望是不变字段的更小字段,无需进行任何调整。日历系统会肯定指望不变的那些字段。 此外,与 set() 不一样,add() 强迫日历系统当即从新计算日历的毫秒数和全部字段!!!!! 示例:假定 GregorianCalendar 最初被设置为 1999 年 8 月 31 日。调用 add(Calendar.MONTH, 13) 将日历设置为 2000 年 9 月 30 日。Add 规则 1 将 MONTH 字段设置为 September,由于向 August 添加 13 个月得出的就是下一年的 September。由于在 GregorianCalendar 中,DAY_OF_MONTH 不多是 9 月 31 日,因此 add 规则 2 将 DAY_OF_MONTH 设置为 30,即最可能的值。尽管它是一个更小的字段,但不能根据规则 2 调整 DAY_OF_WEEK,由于在 GregorianCalendar 中的月份发生变化时,该值也须要发生变化。 roll(f, delta) 将 delta 添加到 f 字段中,但不更改更大的字段。这等同于调用 add(f, delta),但要带如下调整: Roll 规则。在完成调用后,更大的字段无变化。更大的字段表示一个更大的时间单元。DAY_OF_MONTH 是一个比 HOUR 大的字段。 示例:请参阅 GregorianCalendar.roll(int, int)。 使用模型。为了帮助理解 add() 和 roll() 的行为,假定有一个用户界面组件,它带有用于月、日、年和底层 GregorianCalendar 的递增或递减按钮。若是从界面上读取的日期为 1999 年 1 月 31 日,而且用户按下月份的递增按钮,那么应该获得什么?若是底层实现使用 set(),那么能够将该日期读为 1999 年 3 月 3 日。更好的结果是 1999 年 2 月 28 日。此外,若是用户再次按下月份的递增按钮,那么该日期应该读为 1999 年 3 月 31 日,而不是 1999 年 3 月 28 日。经过保存原始日期并使用 add() 或 roll(),根据是否会影响更大的字段,用户界面能够像大多数用户所指望的那样运行。