2011-12-12 57 views
3

我们有一个公共静态util方法,它可以解析一个字符串并返回一个Date对象,但是如果解析的字符串不能转换为Date对象,它也会抛出ParseException。java类中的static final日期字段

现在,在另一个类中,我希望使用上述util方法将静态最终日期初始化为一个值。但是鉴于util方法抛出ParseException,这是不允许的。

这就是我想做的事,这是不允许的

public static final MY_DATE = Util.getDateFromString('20000101'); 

什么是推荐的方法来保持这个日期栏“最终”?

+0

在公共静态字段中可变是很不理想的 – Dapeng

回答

8

那么你可以使用静态初始化块:

public static final Date MY_DATE; 

static { 
    try { 
     MY_DATE = Util.getDateFromString("20000101"); 
    } catch (ParseException e) { 
     ... 
    } 
} 

不过,我会反对这项建议。 Date是一个可变类型 - 通过公共静态final变量暴露它是一个坏主意。

相反,我建议你使用Joda Time其中有许多一成不变日期/时间类型 - 并且是日期和时间的工作彻底更好库。它看起来像你想:

public static final LocalDate START_OF_JANUARY_2000 = new LocalDate(2000, 1, 1); 

请注意,即使你做决定一起去java.util.Date,它并没有多大意义,解析字符串在我看来 - 你知道数字的值,那么为什么不以这种方式供应呢?如果您没有合适的方法来构建从年/月/日开始的Date(推测应用适当的时区),那么您可以轻松编写一个。 OMG!

+0

这不能用'final'关键字编译。它只在我们删除'final'时编译,这就是我们目前代码中的内容。但是你的第二个建议是从年/月/日创建一个日期似乎是合理的。谢谢。 – Ramesh

+1

@Ramesh:如果你让'catch'块引发'RuntimeException'来指示意外的失败,它应该使用'final'进行编译。但是最好不要有一个潜在的异常抛出初始化器... –

+0

util方法来自一个库,我们没有自由来改变签名。我会用你最后的建议直接使用GregorianCalendar的构造函数初始化日期,就像public static final Date = new GregorianCalendar(2000,0,1).getTime(); – Ramesh

2

OMG!我终于得到了一个更好,更精英,更优雅的回答,让Jon Skeet做到了!

一个绝妙的方法是使用一个匿名类,用一个实例块,像这样:

public static final Date MY_DATE = new Date() {{ 
    try { 
     setTime(Util.getDateFromString("20000101").getTime()); 
    } catch (ParseException e) { 
     throw new RuntimeException(e); 
    } 
}}; 

这工作,因为(显着)java.util.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();} 
}; 
+0

我的答案建议使用乔达时间,而不是不可改变的类型,是更好的库开始:) –

+0

@JonSkeet哦,来吧...你必须爱1337变通:)其实,一个组合的乔达和静态实例块的想法可能是去吧。顺便说一句,我把我的帽子给你 - 只有一个人可以得到多少徽章!?你是一个徽章和代表工厂*! – Bohemian

+0

谢谢波西米亚。对于DBI(双大括号初始化)方法为+1。但是我现在可以用Jon提到的最后一个建议去说MY_DATE = new GregorianCalendar(2000,0,1).getTime(); – Ramesh

1

另一种方式,如果你确定你不会实际上获得申报异常,是创造另一种方法,无论是在本地还是在的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是敷衍的。

+0

Perfunctory?..谢谢..我今天学习一个新词。 –

0

它在评论写得很清楚了,而是使之更明确:

public static final MY_DATE = new GregorianCalendar(2000, 1, 1).getTime(); 

做到这一点只有当你可以分配给一个公共静态最后一个可变的日期生活。