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