java类中的静态final Date字段



我们有一个公共静态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();

最新更新