12.1認識Lambda語法
12.1.1Lambda語法概覽
在java中引入了Lambda的同時,與現有API維持兼容性是主要考慮之一。
方法參考的特性,在重用現有API上扮演了重要角色。
重用現有方法操作,可避免到處寫下Lambda表達式。
方法參考不僅避免了重復撰寫Lambda表達式,也可以讓程序代碼更清楚。
12.1.2Lambda表達式與函數接口
在只有Lambda表達式的情況下,參數的類型必須寫出來,如果有目標類型的話,在編譯程序可推斷出類型的情況下,就可以不寫出Lambda表達式的參數類型。
Lambda表達式本身是中性的,不代表任何類型的實例,同樣的Lambda表達式,可用來表示不同目標類型的對象操作。
JDK8的Lambda並沒有導入新類型來作為Lambda表達式的類型,而是就現有的interface語法來定義函數接口,作為Lambda表達式的目標類型。
如果接口使用了@FunctionalInterface來標注,而本身並非函數接口的話,就會引發編譯錯誤。
12.1.3Lambda遇上this與final
Lambda表達式並不是匿名類的語法蜜糖。
Lambda表達式中this的參考對象以及toString()的接受者,是來自Lambda的周圍環境,也就是看Lambda表達式是在哪個名稱范疇,就能參考該范疇內的名稱,像是變量或方法。
在JDK中,如果變量本身等效於final局部變量,也就是說,如果變量不會再匿名類中有重新指定的動作,就可以不用加上final關鍵詞。
如果Lambda表達式中捕獲的局部變量本身等效於final局部變量,可以不用在局部變量上加上final。
在lambda表達式中不可以改變被捕獲的局部變量值。
12.1.4方法與構造函數參考
Lambda表達式只是定義函數接口操作的一種方式,除此之外,只要靜態方法的方法簽署中,參數與返回值定義相同,也可以使用靜態方法來定義函數接口操作。
12.1.5接口默認方法
除了參考靜態方法作為函數接口操作之外,還可以參考特定對象的實例方法。
函數接口操作也可以參考類上定義的非靜態方法,函數接口會試圖用第一個參數方法接受者,而之後的參數依次作為被參考的非靜態方法的參數。
13.1認識時間與日期
13.1.1時間的度量
1.格林威治標准時間(GMT):常被不嚴謹地當成是UTC時間,現已不作為標准時間使用。
2.世界時(UT):在1972年引入UTC之前,GMT與UT是相同的
3.國際原子時(TAI):秒的單位定義是基於TAI,也就是铯原子輻射振動次數。
4.世界協調時間(UTC):UTC考慮了地球自轉越來越慢而有閏秒修正,確保UTC與UT相差不會超過0.9秒。
5.Unix時間:不考慮閏秒修正,用以表達時間軸上某一瞬間
6.epoch:某個特定時代的開始,用以表達時間軸上某一瞬間
13.1.2年歷簡介
1.儒略歷:修正了羅馬歷隔三年設置一閏年的錯誤,改采四年一閏。
2.格裡高利歷:將儒略歷1582年10月4號星期四的隔天,訂為格裡高利歷1582年10月15日星期五。
3.ISO 8601標准,采用統一的數據格式例如:yyyy-mm-ddTHHH:MM:SS.SSS。
13.1.3認識時區
每個地區的標准時間各不相同,涉及到地理、法律、經濟、社會、政治等問題。
考慮了UTC偏移的時間表示上,通常會標識Z符號。
有些高緯度國家,夏季、冬季日照時間差異很大,實施日光節約時間。
13.2認識Date與Calendar
13.2.1時間軸上瞬間的Date
eg:使用Date實例來取得系統時間描述
13.2.2格式化時間日期的DateFormate
DateFormat是個抽象類,其操作類是java.text.SimpleDateFormat,你可以直接構建SimpleDateFormat實例,或是使用DateFormat的getDateInstance()、getTimeInstance()、getDateTimeInstance等靜態方法,用較簡便方式按不同需求取得SimpleDateFormat實例。
eg:如何通過DateFormat的各種靜態方法進行格式化。
eg:直接構建SimpleDateFormat的好處是,可使用模式字符串自定義格式。
eg:SimpleDateFormat有一個parse()方法,可以按構建SimpleDateFormat時指定的格式,將指定的字符串剖析為Date實例,
13.2.3處理時間日期的Calendar
Date現在建議作為時間軸上的瞬間代表,要格式化時間日期則通過DateFormat,如果想要取得某個時間日期信息,或者是對時間日期進行操作,可以使用Calendar實例。
Calendar是個抽象類,java.util.GregorianCalendar是其子類,操作了儒略歷與格裡高利歷的混合歷,通過Calendar的getInstance()取得的Calendar實例,默認就是取得GregorianCalendar實例。
eg:
Calendar calendar = Calendar.getInstance();
取得Calendar實例後,可以使用getTime()取得Data實例,如果想要取得年月日等日期數字時段,可以使用get()方法並指定Calendar上的數字段枚舉常數。
eg:想取得年、月、日字段。
out.println(calendar.get(Calendar.YEAR));
out.println(calendar.get(Calendar.MONTH));
out.println(calendar.get(Calendar.DATE));
如果你要設定時間日期等字段,不要對Date設定,應該使用Calendar,同樣地,月份的部分請使用枚舉常數設定。
eg:
Calendar calendar = Calendar.getInstace();
calendar.set(2016,Calendar.APRIL,16); // 2016/04/16
out.println(calendar.get(Calendar.YEAR)); // 2016
out.println(calendar.get(Calendar.MOUNTH)); //Calendar.APRIL取值3
out.println(calendar.get(Calendar.DATE)); //16
在取得一個Calendar的實例後,可以使用add()方法,來改變Calendar的時間。
eg:
calendar.add(Calendar.MONTH,1); //Calendar時間加1個月
calendar.add(Calendar.HOUR,3); //Calendar時間加3小時
calendar.add(Calendar.YEAR,-2); //Calendar時間減2年
calendar.add(Calendar.DATE,3); //Calendar時間加3天
如果打算只針對日期中某個字段加減,則可以使用roll()方法。
eg:
calendar.roll(Calendar.DATE,1); //只對日字段加1
想比較兩個Calendar的時間日期先後,可以使用after()或before()方法。
eg:使用Calendar計算用戶的歲數。
13.2.4設定TimeZone
使用Calendar時若沒有使用時區信息,則會使用默認時區。
eg:可以使用java.util.TimeZone的getDefault()來取得默認時區信息。
Calendar在調用getInstance()時,可以指定Timezone,如果已經取得Calendar實例,也可以通過setTimeZone()方法設定TimeZone。
eg:想知道現在哥本哈根的時間,並指定TimeZone為北京。
13.3JDK8新時間日期API
13.3.1機器時間觀點的API
由於台灣時區已經不實施日光節約一段時間了,許多開發者並不知道過去有過日光節約時間,在取得Date實例後,被名稱Date誤導他們代表日期,所以不應該使用Data實例來得知人類觀點的時間信息,Date實例只代表機器觀點的時間信息,真正可靠的信息只有內含epoch毫秒數。
同時也可以使用Instant的靜態方法now()取得代表Java epoch毫秒數的Instant實例。
在新舊API兼容上,如果取得了Date實例,而想要改用Instant,則可以調用Date實例的toInstant()方法來取得,如果你有個Instant實例,可以使用Instant的靜態方法from()轉為Date。
13.3.2人類時間觀點的API
1.LocalDateTime、LocalDate和LocalTime
LocalDateTime:包括日期與時間
LocalDate:只有日期,如果設定不存在的日期,會拋出DateTimeException
LocalTime:只有時間
這些類基於ISO 8601年歷系統,是不具時區的時間與日期定義。
對於LocalDateTime.of,由於沒有時區信息,程序無從判斷這個時間是否不存在,就不會拋出DateTimeException
2.ZonedDateTime、OffsetdateTime
eg:如果你的時間日期需要帶有時區,可以基於LocalDateTime、LocalDate、LocalTime等來補充缺少的信息。
3.Year、YearMonth、Month、MonthDay
eg:如果想要取得代表月份的數字,不要使用oridinal()方法,因為oridinal()是enum在定義時的順序,從0開始,想要取得代表月份的數要通過getValue()方法(調整了格式,使其對齊)。
13.3.3對時間的運算
1.TemporalAmount
ofPattern()是java.time.format.DateTimeFormatter的靜態方法,可以查看API文件了解格式化的方式。
對於時間計量,新時間與日期API以類Duration來定義,可用於計量天、時、分、秒的時間差,精度調整可以達納秒等級,而秒的最大值可以是long類型可保存值。
對於年、月、星期、日的日期差,使用Period類定義。
plus()方法可以接受Duration實例來計算
eg:使用新時間與日期API改寫HowOld范例。
2.TemporalUnit
plus()方法另一重載版本,接受java.time.temporal.TemporalUnit實例,java.time.temporal.ChronoUnit是TemporalUnit實作類,使用enum實作。
TemporalUnit定義了between()等方法。
3.Temporal
相對於plus(),也有兩個重載兩個重載版本的minus():
plus(TemporalAmount amount)
plus(long amountToAdd,TemporalUnit unit)
minus(TemporalAmount amount)
minus(long amountToSubtract,TemporalUnit unit)
4.TemporalAccessor
TemporalAccessor定義了只讀的時間對象讀取操作,實際上Temporal是TemporalAccessor子接口,增加了對時間的處理操作,像是plus()、minus()、with()等方法。
13.3.4年歷系統設計
java.time套件中的類在需要實行年歷系統時都是采用單一的ISO8601年歷系統。如需要其他年歷系統,則需要明確實行java.time.chrono中等操作了java.time.chrono.Chronology接口的類。
通過近一個月的學習,我對jave這門課程產生了濃厚的興趣,我希望可以和老師多多互動,多多交流,更好的學習jave。