习题1.2.11
根据Date的API实现一个 SmartDate 类型,在日期非法时抛出一个异常。
要点分析
1. Date
Date类的API如下(课本第48页):
Date类的实现如下(课本第56页):
public class Date { private final int month; private final int day; private final int year; public Date(int m, int d, int y) { month = m; day = d; year = y; } public int month() { return month; } public int day() { return day; } public int year() { return year; } public String toString() { return month() + "/" + day() + "/" + year(); } public static void main(String[] args) { String s = new Date(3,19,1997).toString(); System.out.println(s); } } 输出: 3/19/1997
2. 异常
关于Java异常相关的知识,课本上并没有详细解释,这里也不再赘述,详解可以查看Java异常处理,本题主要用到抛出异常这个知识点。
那么本题中的"日期非法"有哪几种情况呢?
2.1. 非数字
比如我们输入的是三,十九,一九九七,但是该类异常需要在测试类中捕获,所以不在本题的范围内
2.2. 平年闰年
比如2018年2月29日是非法的,闰年2月有29天,平年2月只有28天
2.3. 不存在的日期
比如2018年13月33日是非法的
关于日期主要存在以上几种异常,那么我们如何捕获这些异常呢?
首先,我想到的便是创建一个单独的方法,将年月日挨个使用if else 判断,实现起来比较麻烦。其实我们可以将一个日期转换为字符串再转换成日期,然后采用SimpleDateFormat类的parse方法进行判断[1] ,如果转换不成功,就会出现异常。
public static boolean isValidDate(String str) { boolean convertSuccess=true; // 指定日期格式为四位年/两位月份/两位日期,注意yyyy/MM/dd区分大小写; SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm"); try { // 设置lenient为false. 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01 format.setLenient(false); format.parse(str); } catch (ParseException e) { // e.printStackTrace(); // 如果throw java.text.ParseException或者NullPointerException,就说明格式不对 convertSuccess=false; } return convertSuccess; }
参考答案
import java.text.ParseException; import java.text.SimpleDateFormat; public class Date implements Comparable<Date> { private final int month; private final int day; private final int year; public boolean isValidDate(String str) { boolean convertSuccess = true; SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd"); try { format.setLenient(false); format.parse(str); } catch (ParseException e) { convertSuccess = false; } return convertSuccess; } public Date(int month, int day, int year) { String str = year + "/" + month + "/" + day; if (!isValidDate(str)) { throw new IllegalArgumentException(month + "/" + day + "/" + year + "不合法"); } this.month = month; this.day = day; this.year = year; } public Date(String date) { if (!isValidDate(date)) { throw new IllegalArgumentException(date + "不合法"); } //如果final变量选择在构造函数中初始化,那么当类有多个构造函数时 //需要在每个构造函数中都对这个final变量进行初始化 String[] fields = date.split("/"); //正则表达式 month = Integer.parseInt(fields[0]); day = Integer.parseInt(fields[1]); year = Integer.parseInt(fields[2]); } /* public boolean leap_year(int m, int d, int y) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) { return true; } return false; }*/ public int month() { return month; } public int day() { return day; } public int year() { return year; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Date)) return false; Date date = (Date) o; return month == date.month && day == date.day && year == date.year; } @Override public int hashCode() { int hash = 17; hash = 31*hash + month; hash = 31*hash + day; hash = 31*hash + year; return hash; } @Override public String toString() { return month() + "/" + day() + "/" + year(); } @Override public int compareTo(Date that) { if (this.year < that.year) return -1; if (this.year > that.year) return +1; if (this.month < that.month) return -1; if (this.month > that.month) return +1; if (this.day < that.day) return -1; if (this.day > that.day) return +1; return 0; } public static void main(String[] args) { System.out.println(new Date(2, 29, 2000).toString()); //合法 System.out.println(new Date(2, 290, 2001).toString()); //不合法 System.out.println(new Date(200, 29, 2001).toString());//不合法 } }
参考资料
[1] 孤傲苍狼
请登录之后再进行评论