為什麼阿里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的問題
期待的答案應該是false
。
原因是:
public boolean after(Date when) {
return getMillisOf(this) > getMillisOf(when);
}
static final long getMillisOf(Date date) {
if (date.cdate == null || date.cdate.isNormalized()) {
return date.fastTime;
}
BaseCalendar.Date d = (BaseCalendar.Date) date.cdate.clone();
return gcal.getTime(d);
}
date對象的fastTime值為: 1664429777371
timestamp對象的fastTime值為:1664429777000
看一下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。
總結
不要將java.sql.Timestamp
和其它java.util.Date
的對象比較。