现在的位置: 首页 > 综合 > 正文

java-date类中危险的before和after方法—陷阱(慎用此方法)

2013年08月19日 ⁄ 综合 ⁄ 共 4085字 ⁄ 字号 评论关闭

昨晚修改一个图书馆的续借书籍日期的时候,发现了Date类的before()方法和after()方法,有点小问题。

首先给大家看我演示的第一个结论,直接上代码,代码中有注释

package a;

import java.util.Date;

public class 比较日期 {
	public static void main(String[] args) {
		// A.before(B)返回的是(A在B之前返回true,否则返回false)
		// A.after(B)返回的是(A在B之后返回true,否则返回false)
		Date a = new Date();
		Date b = new Date();
		System.out.println("a.before(a)-->" + a.before(a));
		System.out.println("a.after(a)-->" + a.after(a));
		System.out.println("a.before(b)-->" + a.before(b));
		System.out.println("a.after(b)-->" + a.after(b));
		System.out.println("-----------------------------");
		Date c = new Date(1990, 5, 29);
		System.out.println("a.before(c)-->" + a.before(c));
		System.out.println("a.after(c)-->" + a.after(c));
		System.out.println("c.before(a)-->" + c.before(a));
		System.out.println("c.after(a)-->" + c.after(a));
		// 从上面可以知道:
		// A.before(B)在A<B时,返回true;在A>=B时,返回false;
		// A.after(B)在A>B时,返回true;在A<=B时,返回false;
	}
}

运行的结果如下

a.before(a)-->false
a.after(a)-->false
a.before(b)-->false
a.after(b)-->false
-----------------------------
a.before(c)-->true
a.after(c)-->false
c.before(a)-->false
c.after(a)-->true

细心的读者会发现,上述代码如果日期相同的话,返回的都是false,对吧

然而,问题出现了,请看下面的代码,首先声明一下,今天是2012年11月25号。

package a;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class 比较日期 {
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
		Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日
		Date b = new Date();// 系统的日期,今天是2012/11/25日
		System.out.println("a.before(b)-->" + a.before(b));
		System.out.println("b.before(a)-->" + b.before(a));
		System.out.println("b.after(a)-->" + b.after(a));
		System.out.println("a.after(b)-->" + a.after(b));
		System.out.println("-------------------------------");
		Date c = sdf.parse("2012/11/25");
		System.out.println("a.before(c)-->" + a.before(c));// 也可以说明跟变量的生成时间没有关系
		System.out.println("c.before(a)-->" + c.before(a));// 也可以说明跟变量的生成时间没有关系
	}
}

注意看运行结果,如下

a.before(b)-->true
b.before(a)-->false
b.after(a)-->true
a.after(b)-->false
-------------------------------
a.before(c)-->false
c.before(a)-->false

很明显,结果是按照这两个日期不同来进行判断的,所以才会有上面的运行结果。

其实,上面的运行结果的逻辑是正确的,如果a,b不是在一天的话,方法确实很正确。

但是,上面的运行结果是在a,b是同一天的情况下,那么,明明是同一天,为什么有两个结果不是false呢?

这个问题纠结了我一个晚上,网上也没有解决的办法,于是我细细看了java 的API,汉化后如下

before方法
public boolean before(Date when)测试此日期是否在指定日期之前。 

参数:
when - 日期。 
返回:
当且仅当此 Date 对象表示的瞬间比 when 表示的瞬间早,才返回 true;否则返回 false。 
抛出: 
NullPointerException - 如果 when 为 null。

--------------------------------------------------------------------------------

after方法
public boolean after(Date when)测试此日期是否在指定日期之后。 

参数:
when - 日期。 
返回:
当且仅当此 Date 对象表示的瞬间比 when 表示的瞬间晚,才返回 true;否则返回 false。 
抛出: 
NullPointerException - 如果 when 为 null。

那么瞬间又是指的是什么呢?难道是变量生成的瞬间,生成变量的前后么?跟这个有关系么?

很明显,第一个例子就说明,按照先后顺序,生成变量,如果都是今天的话,返回的是false。说明不是变量生成的瞬间。

如果不相信的话,继续代码贴出来,一看就明白了,下面的这两个代码运行结果是一样的。

package a;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class 比较日期 {
	public static void main(String[] args) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
		Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日
		Date b = new Date();// 系统的日期,今天是2012/11/25日
		System.out.println("a.before(b)-->" + a.before(b));
		System.out.println("b.before(a)-->" + b.before(a));
	}
}
package a;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class 比较日期 {
	public static void main(String[] args) throws ParseException {
		Date b = new Date();// 系统的日期,今天是2012/11/25日
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
		Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日
		System.out.println("a.before(b)-->" + a.before(b));
		System.out.println("b.before(a)-->" + b.before(a));
	}
}

结果都是

a.before(b)-->true
b.before(a)-->false

说明,跟变量生成顺序的先后无关。

那么这个瞬间到底是什么情况呢?这个就不知道了,这个就需要我们查看java的date类的源代码了,它内部的比较的机制是怎么回事呢?

这个我在网上找了找,也没有找到答案,希望哪位大神知道的话,可以告诉我一声。

当然,我自己有一个自己的认识,可以解释这个问题,不知道正确还是错误,遇到

		SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd", Locale.CHINA);
		Date a = sdf.parse("2012/11/25");// 我自己定义的日期,也是2012/11/25日

这个情况的时候,默认是比生成的系统的那个要小的。这样对代码的运行结果,以及API的说明,都无影响。

这个纯属个人观点,我目前的水平只能这样理解,谁有更好的理解方式,可以告诉我。

写这个帖子的目的在于,大家以后使用Date类的时候,一定要小心,日期相同的情况是true还是false,是要看比较的对象是自己定义的,还是系统的。

所以,慎用此方法,能用Calendar类代替就用Calendar类代替。

抱歉!评论已关闭.