为什么阿里Java开发手册不推荐使用Timestamp?
开发手册
网上解释不推荐用java.sql.Date
、java.sql.Time
的文章有很多,但是解释为什么不推荐使用java.sql.Timestamp
文章没找到。
原因
Oracle官网文档中这么写:
可以看到,根源是因为java.sql.Timestamp
父类java.sql.Date
的fastTime
属性存储秒,而java.sql.Timestamp
的nanos
存储秒以外的毫秒。所以秒和毫秒是分别存储的,从Timestamp
的构造方法也可以看出来:
public Timestamp(long time) { // 设置java.sql.Date的fastTime super((time/1000)*1000); // 设置java.sql.Timestamp的nanos if (nanos < 0) { nanos = 1000000000 + nanos; super.setTime(((time/1000)-1)*1000); } }
所以会有什么问题呢?
- equals的问题
The Timestamp.equals(Object) method never returns true when passed an object that isn't an instance of java.sql.Timestamp, because the nanos component of a date is unknown.
可能程序员会想,我两个时间都是从一个millis中创建的,那时间应该是一样的。但是因为Timestamp
的设计,它们的值不相等。
- after的问题
after的问题更加重要。
期待的答案应该是false
,但程序返回的是true
。通过查看源码,找到了after
方法的代码:
public boolean after(Date when) { // 比较mills return getMillisOf(this) > getMillisOf(when); } static final long getMillisOf(Date date) { if (date.cdate == null || date.cdate.isNormalized()) { // 拿fastTime的值做的比较 return date.fastTime; } BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone(); return gcal.getTime(d); }
可以看到,它其实是拿两个对象的fastTime
值做的比较。
打断点,可以看到两个对象的fastTime
值分别为:
date对象的fastTime值为: 1664429777371 timestamp对象的fastTime值为:1664429777000
date的fastTime
值大于timestamp。那这又是为什么呢?
看一下Timestamp的构造方法:
public Timestamp(long time) { // 设置java.sql.Date的fastTime super((time/1000)*1000); // 设置java.sql.Timestamp的nanos if (nanos < 0) { nanos = 1000000000 + nanos; super.setTime(((time/1000)-1)*1000); } }
可以知道timestamp对象的fastTime的后三位为0。
而看Date的构造方法:
public Date(long date) { fastTime = date; }
它是直接把传入的值赋值给fastTime
。
所以此处timestamp的fastTime
值小于date。
总结
不要将java.sql.Timestamp
和其它java.util.Date
及其子类的对象比较。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~