Java 8可謂是自Java 5以來最具革命性的版本了,她在語言、編譯器、類庫、開發工具以及Java虛擬機等方面都帶來了不少新特性。我們來一一回顧一下這些特性。
一、Lambda表達式
Lambda表達式可以說是Java 8最大的賣點,她將函數式編程引入了Java。Lambda允許把函數作為一個方法的參數,或者把代碼看成數據。
一個Lambda表達式可以由用逗號分隔的參數列表、–>符號與函數體三部分表示。例如:
Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );
為了使現有函數更好的支持Lambda表達式,Java 8引入了函數式接口的概念。函數式接口就是只有一個方法的普通接口。java.lang.Runnable與java.util.concurrent.Callable是函數式接口最典型的例子。為此,Java 8增加了一種特殊的注解@FunctionalInterface:
@FunctionalInterface
public interface Functional {
void method();
}
二、接口的默認方法與靜態方法
我們可以在接口中定義默認方法,使用default關鍵字,并提供默認的實現。所有實現這個接口的類都會接受默認方法的實現,除非子類提供的自己的實現。例如:
public interface DefaultFunctionInterface {
default String defaultFunction() {
return "default function";
}
}
我們還可以在接口中定義靜態方法,使用static關鍵字,也可以提供實現。例如:
public interface StaticFunctionInterface {
static String staticFunction() {
return "static function";
}
}
接口的默認方法和靜態方法的引入,其實可以認為引入了C++中抽象類的理念,以后我們再也不用在每個實現類中都寫重復的代碼了。
三、方法引用
通常與Lambda表達式聯合使用,可以直接引用已有Java類或對象的方法。一般有四種不同的方法引用:
構造器引用。語法是Class::new,或者更一般的Class< T >::new,要求構造器方法是沒有參數;
靜態方法引用。語法是Class::static_method,要求接受一個Class類型的參數;
特定類的任意對象方法引用。它的語法是Class::method。要求方法是沒有參數的;
特定對象的方法引用,它的語法是instance::method。要求方法接受一個參數,與3不同的地方在于,3是在列表元素上分別調用方法,而4是在某個對象上調用方法,將列表元素作為參數傳入;
四、重復注解
在Java 5中使用注解有一個限制,即相同的注解在同一位置只能聲明一次。Java 8引入重復注解,這樣相同的注解在同一地方也可以聲明多次。重復注解機制本身需要用@Repeatable注解。Java 8在編譯器層做了優化,相同注解會以集合的方式保存,因此底層的原理并沒有變化。
五、擴展注解的支持
Java 8擴展了注解的上下文,幾乎可以為任何東西添加注解,包括局部變量、泛型類、父類與接口的實現,連方法的異常也能添加注解。
六、Optional
Java 8引入Optional類來防止空指針異常,Optional類最先是由Google的Guava項目引入的。Optional類實際上是個容器:它可以保存類型T的值,或者保存null。使用Optional類我們就不用顯式進行空指針檢查了。
七、Stream
Stream API是把真正的函數式編程風格引入到Java中。其實簡單來說可以把Stream理解為MapReduce,當然Google的MapReduce的靈感也是來自函數式編程。她其實是一連串支持連續、并行聚集操作的元素。從語法上看,也很像linux的管道、或者鏈式編程,代碼寫起來簡潔明了,非常酷帥!
八、Date/Time API (JSR 310)
Java 8新的Date-Time API (JSR 310)受Joda-Time的影響,提供了新的java.time包,可以用來替代 java.util.Date和java.util.Calendar。一般會用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration這些類,對于時間日期的改進還是非常不錯的。
九、JavaScript引擎Nashorn
Nashorn允許在JVM上開發運行JavaScript應用,允許Java與JavaScript相互調用。
十、Base64
在Java 8中,Base64編碼成為了Java類庫的標準。Base64類同時還提供了對URL、MIME友好的編碼器與解碼器。
除了這十大新特性之外,還有另外的一些新特性:
更好的類型推測機制:Java 8在類型推測方面有了很大的提高,這就使代碼更整潔,不需要太多的強制類型轉換了。
編譯器優化:Java 8將方法的參數名加入了字節碼中,這樣在運行時通過反射就能獲取到參數名,只需要在編譯時使用-parameters參數。
并行(parallel)數組:支持對數組進行并行處理,主要是parallelSort()方法,它可以在多核機器上極大提高數組排序的速度。
并發(Concurrency):在新增Stream機制與Lambda的基礎之上,加入了一些新方法來支持聚集操作。
Nashorn引擎jjs:基于Nashorn引擎的命令行工具。它接受一些JavaScript源代碼為參數,并且執行這些源代碼。
類依賴分析器jdeps:可以顯示Java類的包級別或類級別的依賴。
JVM的PermGen空間被移除:取代它的是Metaspace(JEP 122)。
Java 8是一次變化巨大的更新,耗費了工程師大量的時間,還借鑒了很多其它語言和類庫。我們無法在這里一一詳細列舉,以后有機會一定給大家詳細解讀一下。
其實,Java 8/9/X 最早的規劃是
Java 8包含兩個主要項目:
1. Lambda
在Lambda項目中,多核處理器下的Java編程將更高效,Lambda表達式可以幫助開發人員提高效率,更好地利用多核處理器。Lambda項目還包括一個新的處理系統,該系統允許要求代碼建模的編程模式作為數據。新功能一覽:
Lambda表達式的運用
擴展目標類型化
方法和構造函數參考
默認方法
2. Jigsaw
Jigsaw項目的目標是創建一個實用的方式來在JDK上設計和實施一個模塊系統,然后將該系統應用于JDK本身。其關鍵是令大塊的代碼更易于管理,并促進應用和大型運算的代碼重用。Jigsaw項目還帶來了許多新的表單功能,涉及封裝、重構、版本和模塊集成。
此外,除了這兩個項目,Java 8 還增加改進了一些其他語言功能,如升級核心Java庫使并行運算的表達更容易;虛擬擴展方法允許對接口增加方法,為默認實現指定參考;增加新的日期/時間API,同時支持傳感器,增加代碼的部署選項。
我們知道,后來8中,Jigsaw沒來得及做好,只好放到Java 9中了。
Java 9 新特性 極簡介紹
1. Java 平臺級模塊系統
Java 9 的定義功能是一套全新的模塊系統。當代碼庫越來越大,創建復雜,盤根錯節的“意大利面條式代碼”的幾率呈指數級的增長。這時候就得面對兩個基礎的問題: 很難真正地對代碼進行封裝, 而系統并沒有對不同部分(也就是 JAR 文件)之間的依賴關系有個明確的概念。每一個公共類都可以被類路徑之下任何其它的公共類所訪問到, 這樣就會導致無意中使用了并不想被公開訪問的 API。此外,類路徑本身也存在問題: 你怎么知曉所有需要的 JAR 都已經有了, 或者是不是會有重復的項呢? 模塊系統把這倆個問題都給解決了。
模塊化的 JAR 文件都包含一個額外的模塊描述器。在這個模塊描述器中, 對其它模塊的依賴是通過 “requires” 來表示的。另外, “exports” 語句控制著哪些包是可以被其它模塊訪問到的。所有不被導出的包默認都封裝在模塊的里面。如下是一個模塊描述器的示例,存在于 “module-info.java” 文件中:
module blog {
exports com.pluralsight.blog;
requires cms;
}
我們可以如下展示模塊:
請注意,兩個模塊都包含封裝的包,因為它們沒有被導出(使用橙色盾牌可視化)。 沒有人會偶然地使用來自這些包中的類。Java 平臺本身也使用自己的模塊系統進行了模塊化。通過封裝 JDK 的內部類,平臺更安全,持續改進也更容易。
當啟動一個模塊化應用時, JVM 會驗證是否所有的模塊都能使用,這基于 requires
語句——比脆弱的類路徑邁進了一大步。模塊允許你更好地強制結構化封裝你的應用并明確依賴。你可以在這個課程中學習更多關于 Java 9 中模塊工作的信息 。
2. Linking
當你使用具有顯式依賴關系的模塊和模塊化的 JDK 時,新的可能性出現了。你的應用程序模塊現在將聲明其對其他應用程序模塊的依賴以及對其所使用的 JDK 模塊的依賴。為什么不使用這些信息創建一個最小的運行時環境,其中只包含運行應用程序所需的那些模塊呢? 這可以通過 Java 9 中的新的 jlink 工具實現。你可以創建針對應用程序進行優化的最小運行時映像而不需要使用完全加載 JDK 安裝版本。
3. JShell : 交互式 Java REPL
許多語言已經具有交互式編程環境,Java 現在加入了這個俱樂部。您可以從控制臺啟動 jshell ,并直接啟動輸入和執行 Java 代碼。 jshell 的即時反饋使它成為探索 API 和嘗試語言特性的好工具。
測試一個 Java 正則表達式是一個很好的說明 jshell 如何使您的生活更輕松的例子。 交互式 shell 還可以提供良好的教學環境以及提高生產力,您可以在此了解更多信息。在教人們如何編寫 Java 的過程中,不再需要解釋 “public static void main(String [] args)” 這句廢話。
4. 改進的 Javadoc
有時一些小事情可以帶來很大的不同。你是否就像我一樣在一直使用 Google 來查找正確的 Javadoc 頁面呢? 這不再需要了。Javadoc 現在支持在 API 文檔中的進行搜索。另外,Javadoc 的輸出現在符合兼容 HTML5 標準。此外,你會注意到,每個 Javadoc 頁面都包含有關 JDK 模塊類或接口來源的信息。
5. 不可變集合類與集合工廠方法
通常,您希望在代碼中創建一個集合(例如,List 或 Set ),并直接用一些元素填充它。 實例化集合,幾個 “add” 調用,使得代碼重復。 Java 9,添加了幾種集合工廠方法:
Set<Integer> ints = Set.of(1, 2, 3);
List<String> strings = List.of("first", "second");
除了更短和更好閱讀之外,這些方法也可以避免您選擇特定的集合實現。 事實上,從工廠方法返回已放入數個元素的集合實現是高度優化的。這是可能的,因為它們是不可變的:在創建后,繼續添加元素到這些集合會導致 “UnsupportedOperationException” 。
6. 增強Stream API & Reactive Streams
長期以來,Stream API 都是 Java 標準庫最好的改進之一。通過這套 API 可以在集合上建立用于轉換的申明管道。在 Java 9 中它會變得更好。Stream 接口中添加了 4 個新的方法:dropWhile, takeWhile, ofNullable。還有個 iterate 方法的新重載方法,可以讓你提供一個 Predicate (判斷條件)來指定什么時候結束迭代:
IntStream.iterate(1, i -> i < 100, i -> i + 1).forEach(System.out::println);
第二個參數是一個 Lambda,它會在當前 IntStream 中的元素到達 100 的時候返回 true。因此這個簡單的示例是向控制臺打印 1 到 99。
除了對 Stream 本身的擴展,Optional 和 Stream 之間的結合也得到了改進。現在可以通過 Optional 的新方法 stram
將一個 Optional 對象轉換為一個(可能是空的) Stream 對象:
Stream<Integer> s = Optional.of(1).stream();
在組合復雜的 Stream 管道時,將 Optional 轉換為 Stream 非常有用。
7. 私有接口方法
Java 8 為我們帶來了接口的默認方法。 接口現在也可以包含行為,而不僅僅是方法簽名。 但是,如果在接口上有幾個默認方法,代碼幾乎相同,會發生什么情況? 通常,您將重構這些方法,調用一個可復用的私有方法。 但默認方法不能是私有的。 將復用代碼創建為一個默認方法不是一個解決方案,因為該輔助方法會成為公共API的一部分。 使用 Java 9,您可以向接口添加私有輔助方法來解決此問題:
public interface MyInterface {
void normalInterfaceMethod();
default void interfaceMethodWithDefault() { init(); }
default void anotherDefaultMethod() { init(); }
// This method is not part of the public API exposed by MyInterface
private void init() { System.out.println("Initializing"); }
}
如果您使用默認方法開發 API ,那么私有接口方法可能有助于構建其實現。
8. HTTP/2
Java 9 中有新的方式來處理 HTTP 調用。這個遲到的特性用于代替老舊的 HttpURLConnection
API,并提供對 WebSocket 和 HTTP/2 的支持。注意:新的 HttpClient API 在 Java 9 中以所謂的孵化器模塊交付。也就是說,這套 API 不能保證 100% 完成。不過你可以在 Java 9 中開始使用這套 API:
HttpClient client = HttpClient.newHttpClient();
HttpRequest req =
HttpRequest.newBuilder(URI.create("http://www.google.com"))
.header("User-Agent","Java")
.GET()
.build();
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandler.asString());
除了這個簡單的請求/響應模型之外,HttpClient 還提供了新的 API 來處理 HTTP/2 的特性,比如流和服務端推送。
9. 多版本兼容 JAR
我們最后要來著重介紹的這個特性對于庫的維護者而言是個特別好的消息。當一個新版本的 Java 出現的時候,你的庫用戶要花費數年時間才會切換到這個新的版本。這就意味著庫得去向后兼容你想要支持的最老的 Java 版本 (許多情況下就是 Java 6 或者 7)。這實際上意味著未來的很長一段時間,你都不能在庫中運用 Java 9 所提供的新特性。幸運的是,多版本兼容 JAR 功能能讓你創建僅在特定版本的 Java 環境中運行庫程序時選擇使用的 class 版本:
multirelease.jar
├── META-INF
│ └── versions
│ └── 9
│ └── multirelease
│ └── Helper.class
├── multirelease
├── Helper.class
└── Main.class
在上述場景中, multirelease.jar 可以在 Java 9 中使用, 不過 Helper 這個類使用的不是頂層的 multirelease.Helper 這個 class, 而是處在“META-INF/versions/9”下面的這個。這是特別為 Java 9 準備的 class 版本,可以運用 Java 9 所提供的特性和庫。同時,在早期的 Java 諸版本中使用這個 JAR 也是能運行的,因為較老版本的 Java 只會看到頂層的這個 Helper 類。
10. 其他功能改進
Java 10/X 的發展規劃
甲骨文對Java 8 的前景很是看好,并已經開始討論Java 9發展的關鍵領域。比如加入一個self-tuning JVM,提高本地集成和大規模多核的可擴展性;通過新的元對象協議和資源管理器為云應用添加跨語言支持。
甲骨文也表示,Java9和10將加入大數據、多語言的互操作性、云計算和移動,預期分別于2015年和2017年發布。而關于Java開發工具包(JDK)10以及之后的版本也正在討論中,比如使Java語言面向對象,形成一個統一的類型系統,所有原語都將轉換為對象和方法。
隨著使用人數的增加,Java正逐漸成為最常用的編程語言,令每個使用者都滿意成了它的目標。甲骨文認為Java在將來會成為開發者們首選的編程語言,因為它可以實現的東西正好符合了開發者們的期望。
Kotlin
而實際上,Kotlin已經遠遠走在了Java 10的前面了。
比如:
一個統一的類型系統。
多語言的互操作性、云計算和移動端。
更簡單優雅的函數式編程特性支持。
所以,親愛的你, 還在期待 Java X的新特性嗎?
快來直接進入Kotlin的世界吧!!!!
《Kotlin極簡教程》正式上架:
點擊這里 > 去京東商城購買閱讀
點擊這里 > 去天貓商城購買閱讀