我们有一个公共静态util方法,它可以解析字符串并返回Date对象,但是如果解析的字符串不能转换为Date对象,它也会抛出ParseException。
现在,在另一个类中,我想使用上面描述的util方法将静态final Date初始化为一个值。但是考虑到util方法会抛出ParseException,这是不允许的。
这是我想做的,这是不允许的
public static final MY_DATE = Util.getDateFromString('20000101');
建议用什么方法保持Date字段为final ?
你可以使用静态初始化块:
public static final Date MY_DATE;
static {
try {
MY_DATE = Util.getDateFromString("20000101");
} catch (ParseException e) {
// Whatever you want to do here. You might want to throw
// an unchecked exception, or you might want to use some fallback value.
// If you want to use a fallback value, you'd need to use a local
// variable for the result of parsing, to make sure you only have a
// single assignment to the final variable.
}
}
然而,我建议不要这样做。Date
是一个可变类型-通过公共静态final变量公开它是一个坏主意。
从Java 8开始,java.time
包是最适合用于几乎所有日期/时间工作的,您可以这样写:
public static final LocalDate START_OF_JANUARY_2000 = LocalDate.of(2000, 1, 1);
在Java 8之前,我建议您使用Joda Time,它有许多不可变的日期/时间类型——对于处理日期和时间来说,它是一个完全更好的库。看起来你想要:
public static final LocalDate START_OF_JANUARY_2000 = new LocalDate(2000, 1, 1);
注意,即使你做决定去java.util.Date
,它没有多大意义解析字符串在我看来-你知道数值,所以为什么不只是提供他们的方式?如果您还没有一个合适的方法来从年/月/日(大概应用一个适当的时区)构造一个Date
,那么您可以很容易地编写一个。
天哪!我终于可以用一个更好,更精英,更优雅的答案胜过乔恩·斯基特了!
一个简洁的方法是使用一个带有实例块的匿名类,像这样:public static final Date MY_DATE = new Date() {{
try {
setTime(Util.getDateFromString("20000101").getTime());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}};
之所以有效,是因为(值得注意的是)java.util.Date
不是不可变的!
要使Date不可变,从而在设计上更容易被接受,请重写setter方法:
public static final Date MY_DATE = new Date() {{
try {
super.setTime(Util.getDateFromString("20000101").getTime());
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
// Formatted for brevity :)
@Override public void setYear(int year) { throw new UnsupportedOperationException();}
@Override public void setMonth(int month) {throw new UnsupportedOperationException();}
@Override public void setDate(int date) {throw new UnsupportedOperationException();}
@Override public void setHours(int hours) {throw new UnsupportedOperationException();}
@Override public void setMinutes(int minutes) {throw new UnsupportedOperationException();}
@Override public void setSeconds(int seconds) {throw new UnsupportedOperationException();}
@Override public void setTime(long time) {throw new UnsupportedOperationException();}
};
另一种方法是,如果您确定实际上不会获得声明的异常,则可以在本地或Util中创建另一个方法,将ParseException包装在未检查的异常中,如下所示:
public static final Date MY_DATE = getDateFromStringWithoutExploding("20000101");
private static Date getDateFromStringWithoutExploding(String dateString) {
try {
return Util.getDateFromStringWithoutExploding(dateString);
catch(ParseException e) {
throw new IllegalArgumentException(e);
}
}
这是合理的,并且实际上反映了发生的事情-您知道传入的日期字符串是OK的,因此try-catch是敷衍的。
这已经在注释中说明了,但是为了使它更明确:
public static final MY_DATE = new GregorianCalendar(2000, 1, 1).getTime();