【編者按】不管現在你是不是拒絕的,Java 8 越來越近了,各主流框架紛紛推出了支持 Java 8 的新版本,比如 Spring 4,Scala 2.12,Elasticsearch 5 等,做爲 Java 開發語言的使用者還是需要掌握這些新的特性,提升開發效率。
Spring 框架 4 支持 Java 8 語言和 API 功能。在本文中,我們將重點放在 Spring 4 支持新的 Java 8 的功能。最重要的是 Lambda 表達式,方法引用,JSR-310的日期和時間,和可重複註釋。
Lambda 表達式
Spring 的代碼庫使用了 Java 8 大量的函數式接口,Lambda 表達式可以用來編寫更乾淨和緊湊的代碼。每當出現函數式接口的對象的預期時我們便可以提供一個 Lambda 表達式。讓我們進一步繼續之前首先學習函數式接口。
函數式接口
有單一抽象方法的接口被稱爲函數式接口。下面是 JDK 中函數式接口的一些例子:
Comparator 是僅具有一個抽象的非對象方法的函數。儘管聲明瞭兩個抽象方法,因爲 equals
是對應於對象的公共方法所以從計數裏排除了。其中有一個對象類方法且沒有非對象方法的接口並不是函數式接口。
一個接口如果有一個抽象的非對象類方法並且擴展自具有唯一對象類方法的非函數式接口,則稱爲函數式接口。
Spring 框架的函數式接口的例子:
@FunctionalInterface
註解可以在接口聲明的頂部聲明中被使用,但這並不是必需的。此註解用於由編譯器來檢測該接口是不是有效的函數式接口。如果我們試圖在接口裏定義多個單一抽象方法,編譯器將拋出一個錯誤。
函數描述符
接口的函數描述符是該接口的一個抽象方法的方法的類型。該方法類型包括參數類型,返回類型和 throws 子句。
例:
如何編寫 Lambda 表達式
Lambda 表達式的語法可以拆分成三部分:
-
一個箭頭 (–>)
-
參數列表: 一個 Lambda 表達式可以包含0個或多個參數 例:
(String arg) → { System.out.println(“ One argument : ”+arg); }
(String arg1, Integer arg2) → { System.out.println(“Two arguments : ”+arg1+” and ”+arg2); }
- 表達式體:
可以是單個表達式或代碼塊。單個表達式將被簡單地求值並返回。
例:
(String arg) → { System.out.println(“ One argument : ”+arg); }
如果表達式體(Body)中存在語句塊,那麼它將被判定爲方法體,並且在塊執行後隱藏的返回語句將控制權交給調用者。
現在我們看一下如何使用 Lambda 表達式:
例1:
// 使用 Lambda 表達式
例2:
//使用 Lambda 表達式
你可以通過 Spring 的回調函數使用 Lambda 表達式。例如,用一個 ConnectionCallback 檢索給定 JDBC 連接的列表,可寫成如下語句:
jdbcTemplate.execute(connection -> connection.getCatalog())
方法引用
函數式接口也可以使用方法引用來實現,引用方法或構造函數但並不調用它們。方法引用和 Lambda 表達式是類似的,但方法引用是指現有類的方法,而 Lambda 定義了一個匿名方法,並將其作爲函數式接口的實例。
在 Java 8 中一個新增包中包含了常用於 Lambda 表達式和方法引用的函數式接口:java.util.function。
Date Time API
在 Java 中現有的 Date 和 Time 類存在多個問題。Date 和 Calendar 類的最大問題之一是它們不是線程安全的。在編寫日期處理代碼時開發人員不得不特別小心併發問題。Date 類也不支持國際化,因此不支持時區。開發人員必須編寫大量的代碼來支持不同的時區。
Date 和 Time 類也顯現出不佳的 API 設計。java.util.Date
中的月從0,日從1,年從1900開始。缺少一致性。現在這些與 Date 和 Time 類的其它幾個問題在 Java 8 中的新 Date 和 Time API 中已解決。
在 java.time
包下新的 Date 和 Time API 的重要的類是 LocalDate
,LocalTime
和 ZonedDateTime
。
LocalDate 和 LocalTime
LocalDate
表示日期時的默認格式爲 YYYY-MM-DD,並沒有時間。這是一個不可變類。我們可以使用 now()
方法獲得的當前日期。
新建 LocalDate
實例的例子:
//獲取當前日期
我們也可以通過對年,月,日的輸入參數來新建 LocalDate
實例。
// 2016年4月1日
LocalTime
表示無日期的時間,是不變的。時間的默認格式爲 hh:mm:ss.zzz。
新建 LocalTime
實例的例子:
//獲取當前時間
// 18:30:30
默認情況下,LocalDate
和 LocalTime
類使用默認時區的系統時鐘。這些類還提供了通過重載 new()
方法對修改時區的支持。可以通過傳遞 zoneid
來獲得一個特定時區中的日期。
例子:
// 當前本地日期加爾各答(印度)
此外,還有一個類,LocalDateTime
組合了日期和時間,默認格式爲 yyyy-MM-ddTHH:MM:ss.zzz·。
//當前日期和時間
// 2016-04-01 13:30
ZonedDateTime
這是一個不可變的類,用於表示包括時區信息的日期和時間。我們可以使用這個類的一個實例來表示特定事件,如在世界的某些地區一個會議。
// 當前時間使用系統的時間和默認區域
// 當前時間使用特定時區的系統時鐘
Spring 4 提供了一個轉換框架,支持做爲 Java 8 日期和時間 API 一部分的所有類。Spring 4 可以使用一個 2016-9-10 的字符串,並把它轉換成 Java 8 LocalDate
的一個實例。Spring 4 還支持通過 @DateTimeFormat
註解格式化 Java 8 Date-Time 字段。@DateTimeFormat
聲明一個字段應該格式化爲日期時間。
重複註解
在 Java 8 之前,將相同類型的多個註釋加到聲明或類型(例如一個類或方法)中是不允許的。作爲一種變通方法,開發人員不得不將它們組合在一起成爲單個容器註解。
例:
重複註解允許我們重寫相同的代碼並不需顯式地使用容器註解。雖然容器註解沒有在這裏使用的,Java 編譯器負責將兩個註解封裝成一個容器:
例:
定義重複註解
定義一個重複註解,通過可重複使用的 @Repeatable
註解來進行標註,或創建一個具有重複註解類型系列屬性的註解。
第1步:聲明重複註解類型:
第2步:聲明容器註解類型。
全部的實現如下所示:
爲了獲得在運行時的註解信息,通過 @Retention(RetentionPolicy.RUNTIME)
註釋即可。
檢索註解
getAnnotationsByType()
或 getDeclaredAnnotationsByType()
是用於訪問註解反射 API 中的新方法。
註解還可以通過它們的容器註解用 getAnnotation()
或 getDeclaredAnnotation()
進行訪問。
結論
Spring 4 還可運行在 Java 6 和 Java 7 中。由於 Spring 使用了很多的函數式接口,用 Java 8 和 Spring 4,你將能夠使用 Lambda 表達式和函數式接口,並可寫出更乾淨、緊湊的代碼。
新的 Date 和 Time API 解決了 java.Util.Date
類中長期存在的問題,並引入了像 LocalDate
,LocalTime
等許多新類,使日期和時間的編程變得更有意思了。你已經採用 Java 8 + Spring 4 了嗎?請在 Twitter 上 @MyEclipseIDE 或在 MyEclipse 論壇跟我們分享您的反饋。
原文鏈接:https://dzone.com/articles/java-8-features-supported-by-spring-4
本文系 OneAPM 工程師整理呈現。OneAPM 能爲您提供端到端的應用性能解決方案,我們支持所有常見的框架及應用服務器,助您快速發現系統瓶頸,定位異常根本原因。分鐘級部署,即刻體驗,性能監控從來沒有如此簡單。