最近在优化项目代码,看项目组的代码时,发现了一个有趣的现象,有使用new Date().getTime()来获取时间戳的, 也有使用System.currentTimeMillis()来获取时间戳的,这让我想到,好像我平时写代码也是想起哪种方式就用什么方式写。这两种方式都可以,仔细思考一下,两者应该会有区别的,应该有是最优的方式?
然后就看了看源码,其实解决疑惑最优方式就是看源码,打开java.util.Date的源码可以发现,无参构造函数如下:
/**
* Allocates a <code>Date</code> object and initializes it so that
* it represents the time at which it was allocated, measured to the
* nearest millisecond.
*
* @see java.lang.System#currentTimeMillis()
*/
public Date() {
this(System.currentTimeMillis());
}
/**
* Allocates a <code>Date</code> object and initializes it to
* represent the specified number of milliseconds since the
* standard base time known as "the epoch", namely January 1,
* 1970, 00:00:00 GMT.
*
* @param date the milliseconds since January 1, 1970, 00:00:00 GMT.
* @see java.lang.System#currentTimeMillis()
*/
public Date(long date) {
fastTime = date;
}
从源码可以看出,new Date().getTime()其实就是在无参构造里调用了System.currentTimeMillis(),再传入自己的有参构造函数。不难看出,如果只是仅仅获取时间戳,即使是匿名的new Date()对象也会有些许的性能消耗, 从性能提升的角度来看,如果只是仅仅获取时间戳,不考虑时区的影响(时区为什么会有影响),直接调用System.currentTimeMillis()会更好一些。
再来看看System.currentTimeMillis()的源码:
/**
* Returns the current time in milliseconds. Note that
* while the unit of time of the return value is a millisecond,
* the granularity of the value depends on the underlying
* operating system and may be larger. For example, many
* operating systems measure time in units of tens of
* milliseconds.
*
* <p> See the description of the class <code>Date</code> for
* a discussion of slight discrepancies that may arise between
* "computer time" and coordinated universal time (UTC).
*
* @return the difference, measured in milliseconds, between
* the current time and midnight, January 1, 1970 UTC.
* @see java.util.Date
*/
public static native long currentTimeMillis();
这是一个本地方法,其时间来源依赖由操作系统为其做了时区的处理,因此获取时间戳,不需要考虑时区的前提下,它是最优选择。
其实, java.util.Date设计来作为格式化时间,以面向对象的方式获取与时间有关的各方面信息,例如:获取年月份、小时、分钟等等比较丰富的信息。而new Date()来获取当前时间更多的是因为我们使用习惯导致经常第一时间想到用它来获取当前时间。
扩展:关于获取时间戳另一种方式:
在Java中,还可能见到另外一种获取时间的方式:
Calendar.getInstance().getTimeInMillis()
其实这种方式是速度最慢的,看其源码就会发现,Canlendar是区分时区的,因为要处理时区问题会耗费很多的时间。