学习java很痛苦_Java日期细微的痛苦提醒
學習java很痛苦
這些天我不再需要使用java.util.Date了,但是最近選擇這樣做,這讓我想起了使用與Java Date關聯的API的痛苦 。 在這篇文章中,我看了棄用的參數化Date構造函數的一些令人驚訝的API期望,該構造函數接受六個整數 。
在2016年,如果使用Java SE 8編寫新代碼,則Java開發人員很可能會使用Java 8的新Date / Time API,如果使用Java的版本,則可能會使用第三方Java日期/時間庫(例如Joda-Time) 。 Java早于Java8。我選擇最近在一個非常簡單的基于Java的工具中使用Date ,我希望將它作為單個Java源代碼文件交付(無需構建工具即可輕松編譯),并且不依賴于外部的任何庫。 Java SE。 此簡單工具的目標部署環境是Java SE 7,因此不能選擇Java 8 Date / Time API。
接受六個整數的Date構造函數的缺點之一是這六個整數之間的區別,并確保按正確的順序提供它們。 即使強制執行正確的命令,指定月份和年份也會有一些細微的意外。 正確實例化Date對象的最簡單方法也許是通過SimpleDateFormat 。 parse(String)或通過不建議使用的Date(long)構造函數接受從時期零開始的毫秒數。
我的第一個代碼清單演示了一個用0小時,0分鐘和0秒表示一個表示“ 2016年9月26日”的Date實例。 此代碼清單使用String通過SimpleDateFormat.parse(String)實例化Date實例。
final SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_FORMAT); final Date controlDate = formatter.parse(CONTROL_DATE_TIME_STR); printDate("Control Date/Time", controlDate);運行上述命令時,打印結果將達到預期效果,并且輸出日期與為Date實例提供并分析的字符串匹配。
============================================================= = Control Date/Time -> Mon Sep 26 00:00:00 MDT 2016 =============================================================使用接受整數以表示Date實例的不同“字段”的Date構造函數可能會很誘人,但它們會帶來前面提到的細微差別。
下一個代碼清單顯示了一種非常幼稚的方法來調用Date構造函數,該構造函數接受按以下順序表示這些字段的六個整數:年,月,日期,小時,分鐘,秒。
// This will NOT be the intended Date of 26 September 2016 // with 0 hours, 0 minutes, and 0 seconds because both the // "month" and "year" parameters are NOT appropriate. final Date naiveDate = new Date(2016, 9, 26, 0, 0, 0); printDate("new Date(2016, 9, 26, 0, 0, 0)", naiveDate);運行上述代碼的輸出與前面顯示的“控制”案例沒有相同的月份(10月而不是9月)或年份(不是2016年)。
============================================================= = new Date(2016, 9, 26, 0, 0, 0) -> Thu Oct 26 00:00:00 MDT 3916 =============================================================本月比我們預期的要晚(10月而不是9月),因為month參數是從零開始的參數,一月由0表示,九月由8而不是9表示。這是處理以下問題的最簡單方法之一從零開始的月份,對Date構造函數的更可讀的調用是為月份使用適當的java.util.Calendar字段。 下一個示例演示如何使用Calendar.SEPTEMBER進行此操作。
// This will NOT be the intended Date of 26 September 2016 // with 0 hours, 0 minutes, and 0 seconds because the // "year" parameter is not correct. final Date naiveDate = new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0); printDate("new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0)", naiveDate);剛剛列出的代碼段修復了月份規范,但是年份仍然不正確,如下面顯示的關聯輸出所示。
============================================================= = new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Tue Sep 26 00:00:00 MDT 3916 =============================================================這一年仍然相距1900年(而不是2016年為3916年)。 這是因為決定將六整數Date構造函數的第一個整數參數指定為年份,減去1900年。因此,提供“ 2016”作為第一個參數,將年份指定為2016 + 1900 = 3916。要解決此問題,我們需要改為提供116(2016-1900)作為構造函數的第一個int參數。 為了使對此感到驚訝的普通人更容易理解,我喜歡將其字面編碼為2016-1900,如下面的代碼清單所示。
final Date date = new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0); printDate("new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0)", date);在使用從零開始的月份并將預期年份表示為當前年份減去1900的情況下,正確地實例化了Date ,如在下一個輸出列表中所示。
============================================================= = new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Mon Sep 26 00:00:00 MDT 2016 =============================================================Date的Javadoc文檔確實描述了這些細微差別,但這提醒人們,最好使用清晰,可理解的API,不需要注釋中描述的細微差別。 Date(int,int,int,int,int,int)構造函數的Javadoc確實宣告,年需要減去1900,并且月份由0到11之間的整數表示。它還描述了為什么此六整數構造函數已棄用 :“從JDK版本1.1開始,由Calendar.set(年+ 1900,月,日期,小時,分鐘,秒)或GregorianCalendar(年+ 1900,月,日期,小時,分鐘,秒)代替。”
相似的六整數GregorianCalendar(int,int,int,int,int,int)構造函數沒有被棄用,盡管它仍然期望從零開始的month參數,但是當證明證明時,它不希望它減去1900的實際年份。年參數。 當使用適當的Calendar month常數指定月份時,當可以在年份中傳遞2016年并且可以在月份中傳遞Calendar.SEPTEMBER時,API調用將更具可讀性。
我現在很少直接使用Date類,以至于我忘記了它的細微差別,并且在極少數場合讓我再次使用Date時必須重新學習它們。 因此,我將這些有關Date觀察留給我自己。
通過使用他人的API,我們可以學到很多有關什么使API有用且易于學習以及使API更加難以學習的知識。 希望這些經驗教訓將有助于我們編寫自己的API。 這篇文章的重點是Date(int, int, int, int, int, int)構造函數,它提出了一些問題,這些問題導致API不夠理想。 相同類型的多個參數可以輕松地亂序提供參數,而與提供年份和月份有關的“不自然”規則給客戶端開發人員增加了負擔,使他們不得不閱讀Javadoc來理解這些不太明顯的內容規則。
翻譯自: https://www.javacodegeeks.com/2016/09/painful-reminder-java-date-nuances.html
學習java很痛苦
總結
以上是生活随笔為你收集整理的学习java很痛苦_Java日期细微的痛苦提醒的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开业备案证明怎么写(开业备案证明)
- 下一篇: hazelcast_HazelCast的