Java11正式釋出,這幾個逆天新特性教你寫出更牛逼的程式碼

程式設計師小魚發表於2018-10-25

就在前段時間,Oracle 官方宣佈 Java 11 (18.9 LTS) 正式釋出,可在生產環境中使用! 這無疑對我們來說是一大好的訊息。作為一名java開發者來說,雖然又要去學習和了解java11,但內心還是欣慰的。我想至少你和我一樣的心情: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 以後支援的首個長期版本。

為什麼說是長期版本,看下面的官方釋出的支援路線圖表。

上圖是一張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 都有哪些重要的新特性呢?

新特性

1、本地變數型別推斷

什麼是區域性變數型別推斷?

var javastack = "javastack";  
System.out.println(javastack); 

大家看出來了,區域性變數型別推斷就是左邊的型別直接使用 var 定義,而不用寫具體的型別,編譯器能根據右邊的表示式自動推斷型別,如上面的 String 。

var javastack = "javastack"; 

就等於:

String javastack = "javastack"; 

2、字串加強

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

// 判斷字串是否為空白  

" ".isBlank();                // true  

// 去除首尾空格  

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

// 去除尾部空格   

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

// 去除首部空格   

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

// 複製字串  

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

// 行數統計  

"A
B
C".lines().count();    // 3 

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 介面都有。

4、Stream 加強

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

1) 增加單個引數構造方法,可為null

Stream.ofNullable(null).count(); // 0 

2) 增加 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 還不熟悉,可以看之前分享的這一系列教程。

5、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 

6、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);  

} 

7、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 工具包嗎?

8、化繁為簡,一個命令編譯執行原始碼

看下面的程式碼。

// 編譯  
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還是有必要的。主要有兩個原因:

1、Oracle會對Java 11提供長期支援,企業可以放心使用這一版本。並且下一個長期支援的版本會在三年後釋出,時間比較久遠。

2、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


相關文章