Java 11正式發佈,這幾個逆天新特性教你寫出更牛逼的代碼

就在前段時間,Oracle 官方宣佈 Java 11 (18.9 LTS) 正式發佈,可在生產環境中使用! 這無疑對咱們來講是一大好的消息。做爲一名java開發者來講,雖然又要去學習和了解java11,但心裏仍是欣慰的。我想至少你和我同樣的心情:Java在手,天下我有!java

今天咱們來看一下Java 11究竟是什麼、他有什麼特別的、到底要不要升級到Java 11。面試

Java 11有什麼特別的編程

在Oracle官網中,進入下載頁面,第一個可供下載的JDK版本已經提換成了Java SE 11 (LTS),這裏的LTS表示Long-Term-Support。安全

本次發佈的Java 11和2017年9月份發佈的Java 9以及 2018年3月份發佈的Java 10相比,其最大的區別就是:在長期支持(Long-Term-Support)方面,Oracle表示會對Java 11提供大力支持,這一支持將會持續至2026年9月。這是據 Java 8 之後支持的首個長期版本。bash

爲何說是長期版本,看下面的官方發佈的支持路線圖表。異步

上圖是一張Oracle 公佈的對於各個版本的JDK的Support Roadmap。途中列舉了Java 6 - Java 12的正式發佈時間以及支持計劃。模塊化

從中能夠看出,在Java 11以前,Java 9和Java 10是不提供長期支持的,而上一個提供長期支持的版本是Java 8,其將會支持到2025年3月。函數式編程

長期支持,表示Oracle會對其作長期的補丁、安全等擴展支持等。函數

下一個提供長期支持的版本將會是Java 17,其將於2021年發佈。工具

如今大部分都在用 Java 8,Java 9 和 10 目前不多有人在用,至少我沒有發現有公司在生產環境應用的,那就是找死。

如今 Java 11 長期支持,也已經包含了 9 和 10 的所有功能,9 和 10 天然就活到頭了。。

那麼咱們來看下 從 Java 9 - 11 都有哪些重要的新特性呢?

新特性

一、本地變量類型推斷

什麼是局部變量類型推斷?

var javastack = "javastack";  
System.out.println(javastack); 
複製代碼

你們看出來了,局部變量類型推斷就是左邊的類型直接使用 var 定義,而不用寫具體的類型,編譯器能根據右邊的表達式自動推斷類型,如上面的 String 。

var javastack = "javastack"複製代碼

就等於:

String javastack = "javastack"複製代碼

二、字符串增強

Java 11 增長了一系列的字符串處理方法,如如下所示。

// 判斷字符串是否爲空白  

" ".isBlank();                // true  

// 去除首尾空格  

" Javastack ".strip();          // "Javastack"  

// 去除尾部空格   

" Javastack ".stripTrailing();  // " Javastack"  

// 去除首部空格   

" Javastack ".stripLeading();   // "Javastack "  

// 複製字符串  

"Java".repeat(3);             // "JavaJavaJava"  

// 行數統計  

"A\nB\nC".lines().count();    // 3 
複製代碼

三、集合增強

自 Java 9 開始,Jdk 裏面爲集合(List/ Set/ Map)都添加了 of 和 copyOf 方法,它們兩個都用來建立不可變的集合,來看下它們的使用和區別。

示例1:

var list = List.of("Java""Python""C");  

var copy = List.copyOf(list);  

System.out.println(list == copy);   // true 
複製代碼

示例2:

var list = new ArrayList<String>();  

var copy = List.copyOf(list);  

System.out.println(list == copy);   // false 

複製代碼

示例1和2代碼差很少,爲何一個爲true,一個爲false?

來看下它們的源碼:

static <E> List<E> of(E... elements) {  

    switch (elements.length) { // implicit null check of elements  

        case 0:  

            return ImmutableCollections.emptyList();  

        case 1:  

            return new ImmutableCollections.List12<>(elements[0]);  

        case 2:  

            return new ImmutableCollections.List12<>(elements[0], elements[1]);  

        default:  

            return new ImmutableCollections.ListN<>(elements);  

    }  

}  

static <E> List<E> copyOf(Collection<? extends E> coll) {  

    return ImmutableCollections.listCopy(coll);  

}  

static <E> List<E> listCopy(Collection<? extends E> coll) {  

    if (coll instanceof AbstractImmutableList && coll.getClass() != SubList.class) {  

        return (List<E>)coll;  

    } else {  

        return (List<E>)List.of(coll.toArray());  

    }  

} 
複製代碼

能夠看出 copyOf 方法會先判斷來源集合是否是 AbstractImmutableList 類型的,若是是,就直接返回,若是不是,則調用 of 建立一個新的集合。

示例2由於用的 new 建立的集合,不屬於不可變 AbstractImmutableList 類的子類,因此 copyOf 方法又建立了一個新的實例,因此爲false.

注意:使用 of 和 copyOf 建立的集合爲不可變集合,不能進行添加、刪除、替換、排序等操做,否則會報 java.lang.UnsupportedOperationException 異常。

上面演示了 List 的 of 和 copyOf 方法,Set 和 Map 接口都有。

四、Stream 增強

Stream 是 Java 8 中的新特性,Java 9 開始對 Stream 增長了如下 4 個新方法。

  1. 增長單個參數構造方法,可爲null
Stream.ofNullable(null).count(); // 0 
複製代碼
  1. 增長 takeWhile 和 dropWhile 方法
Stream.of(1, 2, 3, 2, 1)  

    .takeWhile(n -> n < 3)  

    .collect(Collectors.toList());  // [1, 2] 
複製代碼

從開始計算,當 n < 3 時就截止。

Stream.of(1, 2, 3, 2, 1)  

    .dropWhile(n -> n < 3)  

    .collect(Collectors.toList());  // [3, 2, 1] 
複製代碼

這個和上面的相反,一旦 n < 3 不成立就開始計算。

3)iterate重載

這個 iterate 方法的新重載方法,可讓你提供一個 Predicate (判斷條件)來指定何時結束迭代。

若是你對 JDK 8 中的 Stream 還不熟悉,能夠看以前分享的這一系列教程。

五、Optional 增強

Opthonal 也增長了幾個很是酷的方法,如今能夠很方便的將一個 Optional 轉換成一個 Stream, 或者當一個空 Optional 時給它一個替代的。

Optional.of("javastack").orElseThrow();     // javastack  

Optional.of("javastack").stream().count();  // 1  

Optional.ofNullable(null)  

    .or(() -> Optional.of("javastack"))  

    .get();   // javastack 
複製代碼

六、InputStream 增強

InputStream 終於有了一個很是有用的方法:transferTo,能夠用來將數據直接傳輸到 OutputStream,這是在處理原始數據流時很是常見的一種用法,以下示例。

var classLoader = ClassLoader.getSystemClassLoader();  

var inputStream = classLoader.getResourceAsStream("javastack.txt");  

var javastack = File.createTempFile("javastack2""txt");  

try (var outputStream = new FileOutputStream(javastack)) {  

    inputStream.transferTo(outputStream);  

} 
複製代碼

七、HTTP Client API

這是 Java 9 開始引入的一個處理 HTTP 請求的的孵化 HTTP Client API,該 API 支持同步和異步,而在 Java 11 中已經爲正式可用狀態,你能夠在 java.net 包中找到這個 API。

來看一下 HTTP Client 的用法:

var request = HttpRequest.newBuilder()  

    .uri(URI.create("https://javastack.cn"))  

    .GET()  

    .build();  

var client = HttpClient.newHttpClient();  

// 同步  

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());  

System.out.println(response.body());  

// 異步  

client.sendAsync(request, HttpResponse.BodyHandlers.ofString())  

    .thenApply(HttpResponse::body)  

    .thenAccept(System.out::println); 
複製代碼

上面的 .GET() 能夠省略,默認請求方式爲 Get!

更多使用示例能夠看這個 API,後續有機會再作演示。

如今 Java 自帶了這個 HTTP Client API,咱們之後還有必要用 Apache 的 HttpClient 工具包嗎?

八、化繁爲簡,一個命令編譯運行源代碼

看下面的代碼。

// 編譯  
javac Javastack.java  


// 運行  
java Javastack 
複製代碼

在咱們的認知裏面,要運行一個 Java 源代碼必須先編譯,再運行,兩步執行動做。而在將來的 Java 11 版本中,經過一個 java 命令就直接搞定了,如如下所示。

java Javastack.java 
複製代碼

更多新特性

新發布的Java 11在新特性方面,提供了17個JEP(JDK Enhancement Proposal 特性加強提議)

上圖是Oracle公佈的Java 11包含的全部新特性,其中幾個重點的新特性爲:

ZGC:可擴展的低延遲垃圾收集器

ZGC是一款號稱能夠保證每次GC的停頓時間不超過10MS的垃圾回收器,而且和當前的默認垃圾回收起G1相比,吞吐量降低不超過15%。

Epsilon:什麼事也不作的垃圾回收器

Java 11還加入了一個比較特殊的垃圾回收器——Epsilon,該垃圾收集器被稱爲「no-op」收集器,將處理內存分配而不實施任何實際的內存回收機制。 也就是說,這是一款不作垃圾回收的垃圾回收器。這個垃圾回收器看起來並沒什麼用,主要能夠用來進行性能測試、內存壓力測試等,Epsilon GC能夠做爲度量其餘垃圾回收器性能的對照組。大神Martijn說,Epsilon GC至少可以幫助理解GC的接口,有助於成就一個更加模塊化的JVM。

加強var用法

Java 10中增長了本地變量類型推斷的特性,可使用var來定義局部變量。儘管這一特性被不少人詬病,可是並不影響Java繼續加強他的用法,在Java 11中,var能夠用來做爲Lambda表達式的局部變量聲明。

移除Java EE和CORBA模塊

早在發佈Java SE 9的時候,Java就表示過,會在將來版本中將Java EE和CORBA模塊移除,而這樣舉動終於在Java 11中實施。終於去除了Java EE和CORBA模塊。

HTTP客戶端進一步升級

JDK 9 中就已對 HTTP Client API 進行標準化,而後經過JEP 110,在 JDK 10 中進行了更新。在本次的Java 11的更新列表中,由以JEP 321進行進一步升級。該API經過CompleteableFutures提供非阻塞請求和響應語義,能夠聯合使用以觸發相應的動做。 JDK 11徹底重寫了該功能。如今,在用戶層請求發佈者和響應發佈者與底層套接字之間追蹤數據流更容易了,這下降了複雜性,並最大程度上提升了HTTP / 1和HTTP / 2之間的重用的可能性。

到底要不要升級

2017年8月,JCP執行委員會提出將Java的發佈頻率改成每六個月一次。

  • 2017年9月,Java 9發佈。
  • 2018年3月,Java 10發佈。
  • 2018年9月,Java 11發佈。

大部分人使用的JDK版本仍是Java 8及如下版本,甚至某些公司的生產環境使用的仍是JDK 1.6。

那麼,對於公司和開發者來講,到底要不要在生產及開發環境中升級和學習Java 11呢?

對於企業來講

對於企業來講,生產環境中的JDK版本升級到Java 11仍是有必要的。主要有兩個緣由:

一、Oracle會對Java 11提供長期支持,企業能夠放心使用這一版本。而且下一個長期支持的版本會在三年後發佈,時間比較久遠。

二、Java 11確實提供了一些比較不錯的特性,尤爲重要的是提供了ZGC,這是一款具備劃時代意義的垃圾回收器。優勢再也不贅述。有了ZGC,JVM的性能瓶頸能夠被突破。

對於開發者來講

在編碼方面,Java 11並無像Java 8那樣變化巨大,畢竟Java 8提供了函數式編程的能力,這也是不少開發者學習Java 8的一個重要緣由。

可是,Java 11也並非徹底沒有提高,至少在新版本中,Java開發者終於能夠擺脫老舊的HttpURLConnection了。新的HTTP API提供了對HTTOP/2等業界前沿標準的支持,提供了精簡而又友好的API接口。

因此,綜上所述,不管是對於企業仍是開發者來講,升級Java 11都是有必要的,至少比Java 9和Java 10的必要性要大不少。至於這個必要性到底有多大呢,做者給一個簡單的說明:

  • 若是你如今時候用的JDK/Java版本低於Java 8,先升級到Java 8。
  • 若是你如今時候用的JDK/Java版本高於Java 7,那麼能夠考慮升級到Java 11了。 固然,你能夠直接從Java 6跳躍到Java 11。

最後

如今許多人還在使用 Java 8 或者 7,不過 8 在 2019 年初就會結束免費更新。如今 11 是長期支持版本,正是學習和上手 11 的好時機,寫這篇文章但願能對你有所啓發。

閱讀更多

還有這種操做?淺析爲何要看源碼

上次發版我就改了一行代碼!

MongoDB、Hbase、Redis等NoSQL優劣勢、應用場景

31道Android面試題 ,牢固你的基礎!

相信本身,沒有作不到的,只有想不到的

在這裏得到的不只僅是技術!

image
相關文章
相關標籤/搜索