谜题61:日期游戏
下面的程序演練了Date和Calendar類的某些基本特性,它會打印出什么呢?
import java.util.*;public class DatingGame {public static void main(String[ ] args) { Calendar cal = Calendar.getInstance(); cal.set(1999, 12, 31); // Year, Month, Day System.out.print(cal.get(Calendar.YEAR) + " "); Date d = cal.getTime(); System.out.println(d.getDay()); } }該程序創建了一個Calendar實例,它應該表示的是1999年的除夕夜,然后該程序打印年份和日??雌饋碓摮绦驊摯蛴?999 31,但是它沒有;它打印的是2000 1。難道這是致命的Y2K(千年蟲)問題嗎?
不,事情比我們想象的要糟糕得多:這是致命的Date/Calendar問題。在Java平臺首次發布時,它唯一支持日歷計算類的就是Date類。這個類在能力方面是受限的,特別是當需要支持國際化時,它就暴露出了一個基本的設計缺陷:Date實例是易變的。在1.1版中,Calendar類被添加到了Java平臺中,以矯正Date的缺點,由此大部分的Date方法就都被棄用了。遺憾的是,這么做只能使情況更糟。我們的程序說明Date和Calendar API有許多問題。
該程序的第一個bug就位于方法調用cal.set(1999,12,31)中。當月份以數字來表示時,習慣上我們將第一個月被賦值為1。遺憾的是,Date將一月表示為0,而Calendar延續了這個錯誤。因此,這個方法調用將日歷設置到了1999年第13個月的第31天。但是標準的(西歷)日歷只有12個月,該方法調用肯定應該拋出一個IllegalArgumentException異常,對嗎?它是應該這么做,但是它并沒有這么做。Calendar類直接將其替換為下一年,在本例中即2000年的第一個月。這也就解釋了我們的程序為什么打印出的第一個數字是2000。
有兩種方法可以訂正這個問題。你可以將cal.set調用的第二個參數由12改為11,但是這么做容易引起混淆,因為數字11會讓讀者誤以為是11月。更好的方式是使用Calendar專為此目的而定義的常量,即Calendar.DECEMBER。
該程序打印出的第二個數字又是怎么回事呢?cal.set調用很明顯是要把日歷設置到這個月的第31天,Date實例d表示的是與Calendar相同的時間點,因此它的getDay方法應該返回31,但是程序打印的卻是1,這是怎么搞得呢?
為了找出原因,你必須先閱讀一下文檔,它敘述道Date.getDay返回的是Date實例所表示的星期日期,而不是月份日期。這個返回值是基于0的,從星期天開始計算。因此程序所打印的1表示2000年1月31日是星期一。請注意,相應的Calendar方法get(Calendar.DAY_OF_WEEK) 不知為什么返回的是基于1的星期日期值,而不是像Date的對應方法那樣返回基于0的星期日期值。
有兩種方法可以訂正這個問題。你可以調用Date.date這一名字極易讓人混淆的方法,它返回的是月份日期。然而,與大多數Date方法一樣,它已經被棄用了,因此你最好是將Date徹底拋棄,直接調用Calendar的get(Calendar.DAY_OF_MONTH)方法。用這兩種方法,該程序都可以打印出我們想要的1999 31:
public class DatingGame {public static void main(String[] args) { Calendar cal = Calendar.getInstance(); cal.set(1999, Calendar.DECEMBER, 31); System.out.print(cal.get(Calendar.YEAR) + " "); System.out.println(cal.get(Calendar.DAY_OF_MONTH)); } }本謎題只是掀開了Calendar和Date缺陷的冰山一角。這些API簡直就是雷區。Calendar其他的嚴重問題包括弱類型(幾乎每樣事物都是一個int)、過于復雜的狀態空間、拙劣的結構、不一致的命名以及不一致的雨衣等。在使用Calendar和Date的時候一定要當心,千萬要記著查閱API文檔。
對API設計者來說,其教訓是:如果你不能在第一次設計時就使它正確,那么至少應該在第二次設計時應該使它正確,絕對不能留到第三次設計時去處理。如果你對某個API的首次嘗試出現了嚴重問題,那么你的客戶可能會原諒你,并且會再給你一次機會。如果你第二次嘗試又有問題,你可能會永遠堅持這些錯誤了。
轉載于:https://www.cnblogs.com/yuyu666/p/9840996.html
總結
- 上一篇: qq邮箱电脑登录入口(qq邮箱网上登录入
- 下一篇: 电脑硬盘扇区是什么(磁盘分区的扇区是什么