Calendar类toString方法返回数据不一致问题求助
Java Calendar.toString() 输出不一致的原因分析
这段测试代码里,两次完全相同的断言结果却截然不同:第一次执行成功,但在调用calendar.get(Calendar.DAY_OF_YEAR)后,第二次断言直接失败。我已经找到问题的规避方法,最初推测是toString()方法存在bug,实际是Calendar的设计特性导致的差异。
测试代码如下:
// Calendar calendar = new Calendar.Builder().setDate(2024, Calendar.JANUARY, 25).build(); Calendar calendar = Calendar.getInstance(); calendar.set(2024, Calendar.JANUARY, 25); assertThat(calendar.toString(), not(containsString("DAY_OF_YEAR=25"))); // success assertEquals(25, calendar.get(Calendar.DAY_OF_YEAR)); // success assertThat(calendar.toString(), not(containsString("DAY_OF_YEAR=25"))); // fail
核心原因
Calendar采用延迟计算的设计逻辑:
- 调用
set()方法设置年月日时,Calendar仅记录这些显式设置的字段,不会立刻计算派生字段(比如DAY_OF_YEAR)。 - 第一次调用
toString()时,输出的只有已显式设置的字段,此时DAY_OF_YEAR还未被计算,所以输出里没有这个字段,断言成功。 - 当调用
get(Calendar.DAY_OF_YEAR)时,Calendar会触发全字段同步计算,DAY_OF_YEAR会被计算为25并缓存下来。 - 第二次调用
toString()时,已缓存的DAY_OF_YEAR字段会被包含在输出中,导致断言失败。
这并非toString()的bug,而是Calendar为了性能优化采用的延迟计算机制,引发了前后两次输出的差异。
内容的提问来源于stack exchange,提问作者Ilya
相关产品推荐
相关产品推荐

