2011-12-12 28 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(); 

做到這一點只有當你可以分配給一個公共靜態最後一個可變的日期生活。