Java9新特性

作者:「Rambabu Posa」,一個(gè)具有 11 年豐富開發(fā)經(jīng)驗(yàn)的技術(shù)牛人。

英文出處:Java 9 Features with Examples

  • Java 9 REPL (JShell)
  • Factory Methods for Immutable List, Set, Map and Map.Entry
  • Private methods in Interfaces
  • Moduar System - Jigsaw Project
  • Process API Improvements
  • Try With Resources Improvement
  • CompletableFuture API Improvement
  • Reactive Streams
  • Diamond Operator for Anonymous Inner Class
  • Optional Class Improvements
  • Stream API Improvements
  • Enhanced @Deprecated annotation
  • HTTP 2 Client
  • Мulti-Resolution Image API

1、Java 9 REPL (JShell)

Oracle 公司(Java Library 開發(fā)者)新引進(jìn)一個(gè)代表 Java Shell 的稱之為 “jshell” 或者 REPL(Read Evaluate Print Loop)的新工具。該工具可以被用來執(zhí)行和測(cè)試任何 Java 中的結(jié)構(gòu),如 class,interface,enum,object,statements 等。使用非常簡(jiǎn)單。

$ jshell
|  Welcome to JShell -- Version 9.0.1
|  For an introduction type: /help intro

jshell> System.out.println("Hello World!");
Hello World!

我們同樣可以定義和執(zhí)行類的方法

jshell> class Hello {
   ...> public static void sayHello() {
   ...> System.out.print("Hello");
   ...> }
   ...> }
|  created class Hello

jshell> Hello.sayHello()
Hello

想要了解更多的功能的話可以執(zhí)行"/help",它會(huì)告訴你許多你想知道的,另外退出命令是"/exit"。

2、Factory Methods for Immutable List, Set, Map and Map.Entry

Oracle 公司引入一些方便使用的工廠方法,用于創(chuàng)建不可變集合 List,Set,Map 和 Map.Entry 對(duì)象。這些高效實(shí)用的方法可用來創(chuàng)建空或者非空集合對(duì)象。
在 Java SE 8 和更早版本中,我們常用類似 unmodifiableXXX 的集合類方法創(chuàng)建不可變集合對(duì)象。舉個(gè)例子,比如我們想創(chuàng)建一個(gè)不可變的 List 對(duì)象,可能使用到 Collections.unmodifiableList 方法。
然而,這些 Collections.unmodifiableXXX 方法顯得非常冗長(zhǎng)乏味。為了克服這些缺陷,Oracle 公司給 List、Set 和 Map 接口分別添加了兩個(gè)更加實(shí)用的方法。
List 和 Set 接口使用 of() 方法創(chuàng)建一個(gè)空或者非空的不可變 List 或 Set 對(duì)象

List immutableList = List.of();
List immutableList = List.of("one","two","three");
 Map<Integer,String> emptyMap = new HashMap<>();
 Map<Integer,String> immutableEmptyMap = Collections.unmodifiableMap(emptyMap);
jshell> Map emptyImmutableMap = Map.of()
emptyImmutableMap ==> {}
Map<Integer,String> nonemptyMap = new HashMap<>();
 nonemptyMap.put(1,"one")
 nonemptyMap.put(2,"two")
 nonemptyMap.put(3,"three")
 Map<Integer,String> immutableNonEmptyMap = Collections.unmodifiableMap(nonemptyMap);
jshell> Map nonemptyImmutableMap = Map.of(1, "one", 2, "two", 3, "three")
nonemptyImmutableMap ==> {2=two, 3=three, 1=one}
jshell> import static java.util.Map.entry

jshell> Map<Integer,String> nonemptyMap = Map.ofEntries(entry(1,"one"),entry(2,"two"));
nonemptyMap ==> {2=two, 1=one}

3、Private methods in Interfaces

在 Java SE 8 中,我們可以在接口中使用默認(rèn)或者靜態(tài)方法提供一些實(shí)現(xiàn)方式,但是不能創(chuàng)建私有方法。
為了避免冗余代碼和提高重用性,Oracle 公司準(zhǔn)備在 Java SE 9 接口中引入私有方法。也就是說從 Java SE 9 開始,我們也能夠在接口類中使用 ‘private’ 關(guān)鍵字寫私有化方法和私有化靜態(tài)方法。
接口中的私有方法與 class 類中的私有方法在寫法上并無差異,如:

public interface Card{

  private Long createCardID(){
    // Method implementation goes here.
  }

  private static void displayCardDetails(){
    // Method implementation goes here.
  }

}

Java9接口中可以存在的東西:

  1. 常量
  2. Abstract methods
  3. Default methods
  4. Static methods
  5. Private methods
  6. Private Static methods

4、Java9 Module System

Java SE 9 新特性中最大的一個(gè)變化就是 Module System。Oracle 公司將引入如下特性:

  • Modular JDK
  • Modular Java Source Code
  • Modular Run-time Images
  • Encapsulate Java Internal APIs
  • Java Platform Module System

Java SE 9 版本之前,我們使用整體的 Jars 來開發(fā)基于 Java 語言的應(yīng)用程序。這種體系架構(gòu)有許多局限性和缺點(diǎn)。為了避免這些缺陷,Java SE 9 迎來了 Module System。

模塊化的優(yōu)點(diǎn):

JDK,JRE,JARs都變成了更小的模塊,我們可以運(yùn)用任何我們想要的
易于測(cè)試與維護(hù)
支持更好的性能
更強(qiáng)的封裝
我們無法訪問內(nèi)部非關(guān)鍵的api
模塊可以非常安全地隱藏不需要的和內(nèi)部的細(xì)節(jié),我們可以獲得更好的安全性。
jdk的對(duì)比:


jdk8_jdk9.png

JDK8文件結(jié)構(gòu):


JDK8

JDK9文件結(jié)構(gòu):
JDK9

所有的JDK模塊以"jdk"開頭,所有Java SE規(guī)范模塊以"java"開頭,"java.base"模塊是“The Mother of Java 9 Module"。
image

image

image
  • 每個(gè)模塊有唯一一個(gè)名字
  • 每個(gè)模塊在源文件中都有一些描述
  • 模塊描述在一個(gè)名為“module-info.java”的源文件中表示,"module-info.java"描述一個(gè)模塊。
  • 模塊描述符是一個(gè)Java文件。它不是XML,文本文件或?qū)傩晕募?/li>
  • 按照約定,模塊描述符文件放置在模塊的頂層目錄中
  • 每個(gè)模塊可以有任意數(shù)量的包和類型
  • 一個(gè)模塊可以依賴于任意數(shù)量的模塊
java

“module”, “requires”, and “exports”并不是java關(guān)鍵字。

5、Process API Improvements

Java SE 9 迎來一些 Process API 的改進(jìn),通過添加一些新的類和方法來優(yōu)化系統(tǒng)級(jí)進(jìn)程的管控。

Process API 中的兩個(gè)新接口:

  • java.lang.ProcessHandle
  • java.lang.ProcessHandle.Info
ProcessHandle currentProcess = ProcessHandle.current();
System.out.println("Current Process Id: = " + currentProcess.getPid());

6、Try With Resources Improvement

我們知道,Java SE 7 引入了一個(gè)新的異常處理結(jié)構(gòu):Try-With-Resources,來自動(dòng)管理資源。這個(gè)新的聲明結(jié)構(gòu)主要目的是實(shí)現(xiàn)“Automatic Better Resource Management”(“自動(dòng)資源管理”)。
Java SE 9 將對(duì)這個(gè)聲明作出一些改進(jìn)來避免一些冗長(zhǎng)寫法,同時(shí)提高可讀性。

Java SE 7中:
  • 任何資源(預(yù)定義的Java API類或用戶定義的類)都必須實(shí)現(xiàn)Java.lang.autocloseable
  • 資源對(duì)象必須引用final或有效的final變量
  • 如果資源已經(jīng)在try-with-Resource語句之外聲明,那么我們應(yīng)該重新引用局部變量
  • 新創(chuàng)建的本地變量在try-with-resources語句中是有效的
void testARM_Before_Java9() throws IOException{
  BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
  try (BufferedReader reader2 = reader1) {
    System.out.println(reader2.readLine());
  }
}
void testARM_Java9() throws IOException{
  BufferedReader reader1 = new BufferedReader(new FileReader("test.txt"));
  try (reader1) {
    System.out.println(reader1.readLine());
  }
}

7、CompletableFuture API Improvement

在 Java SE 9 中,Oracle 公司將改進(jìn) CompletableFuture API 來解決一些 Java SE 8 中出現(xiàn)的問題。這些被添加的 API 將用來支持一些延時(shí)和超時(shí)操作,實(shí)用方法和更好的子類化。

Executor exe = CompletableFuture.delayedExecutor(50L, TimeUnit.SECONDS);

這里的 delayedExecutor() 是靜態(tài)實(shí)用方法,用來返回一個(gè)在指定延時(shí)時(shí)間提交任務(wù)到默認(rèn)執(zhí)行器的新 Executor 對(duì)象。

8、Reactive Streams

現(xiàn)在,Reactive Programming 由于其便利性在應(yīng)用程序開發(fā)中變得非常流行。Scala、Play、Akka 等框架已經(jīng)集成 Reactive Streams 并且受益良多。Oracle 公司也在 Java SE 9 中引入了一個(gè)新的 Reactive Streams API。
Java SE 9 Reactive Streams API 是一個(gè)發(fā)布訂閱型框架,使我們能夠非常簡(jiǎn)單地使用 Java 語言就能實(shí)現(xiàn)異步的、可拓展的和并行的應(yīng)用。
Java SE 9 引進(jìn)下面這些 API 來在基于 Java 語言的應(yīng)用中開發(fā) Reactive Streams:

  • java.util.concurrent.Flow
  • java.util.concurrent.Flow.Publisher
  • java.util.concurrent.Flow.Subscriber
  • java.util.concurrent.Flow.Processor

9、Diamond Operator for Anonymous Inner Class

我們知道,Java SE 7 引入了一個(gè)新的特性:Diamond Operator,來避免冗長(zhǎng)代碼和提升可讀性。然而在 Java SE 8 中,Oracle 公司發(fā)現(xiàn)在 Diamond 操作器和匿名內(nèi)部類的使用中存在一些局限性,后來修復(fù)了這些問題并準(zhǔn)備將其作為 Java 9 的一部分發(fā)布出去

List<String> list = new ArrayList <>(){};

10、Optional Class Improvements

在 Java SE 9 中,Oracle 公司添加了一些新的實(shí)用方法到 java.util.Optional 類里面。這里我將使用一些簡(jiǎn)單的示例來描述其中的一個(gè):stream 方法。
如果一個(gè)值出現(xiàn)在給定 Optional 對(duì)象中,stream() 方法可以返回包含該值的一個(gè)順序 Stream 對(duì)象。否則,將返回一個(gè)空 Stream。
stream() 方法已經(jīng)被添加,并用來在 Optional 對(duì)象中使用,如

  • stream()
Stream<Optional> emp = getEmployee(id)
Stream empStream = emp.flatMap(Optional::stream)
  • ifPresentOrElse()
public void ifPresentOrElse(Consumerl<? super Tl> action, Runnable emptyAction)
jshell> Optional<Integer> opt1 = Optional.of(4)
opt1 ==> Optional[4]

jshell> opt1.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Result found: 4

jshell> Optional<Integer> opt2 = Optional.empty()
opt2 ==> Optional.empty

jshell> opt2.ifPresentOrElse( x -> System.out.println("Result found: " + x), () -> System.out.println("Not Found."))
Not Found.
  • or()
public Optional<T> or(Supplier<? extends Optional<? extends T>> supplier)
jshell> Optional<String> opStr = Optional.of("Rams")
opStr ==> Optional[Rams]

jshell> import java.util.function.*

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$5 ==> Optional[Rams]
jshell> Optional<String> opStr = Optional.empty()
opStr ==> Optional.empty

jshell> Supplier<Optional<String>> supStr = () -> Optional.of("No Name")
supStr ==> $Lambda$67/222624801@23faf8f2

jshell> opStr.or(supStr)
$7 ==> Optional[No Name]

11、Stream API Improvements

在 Java SE 9 中,Oracle 公司添加了四個(gè)非常有用的新方法到 java.util.Stream 接口里面。正如 Stream 作為一個(gè)接口類,所有這些新的實(shí)現(xiàn)方法都是默認(rèn)方法。其中有兩個(gè)方法非常重要:dropWhile 和 takeWhile。
如果你熟悉 Scala 語言或者其它函數(shù)編程語言的話,你一定知道這些方法。他們?cè)趯懸恍┕δ軜邮酱a時(shí)非常有用。
這個(gè) takeWhile() 方法使用一個(gè)斷言作為參數(shù),返回給定 Stream 的子集直到斷言語句第一次返回 false。如果第一個(gè)值不滿足斷言條件,將返回一個(gè)空的 Stream。

  • takeWhile
default Stream<T> takeWhile(Predicate<? super T> predicate)

有序

jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2
3

無序

jshell> Stream<Integer> stream = Stream.of(1,2,4,5,3,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.takeWhile(x -> x < 4).forEach(a -> System.out.println(a))
1
2
  • dropWhile

在Stream API中,dropWhile()方法刪除了與斷言匹配的最長(zhǎng)的前綴元素,并返回其他元素。

default Stream<T> dropWhile(Predicate<? super T> predicate)
jshell> Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10)
stream ==> java.util.stream.ReferencePipeline$Head@55d56113

jshell> stream.dropWhile(x -> x < 4).forEach(a -> System.out.println(a))
4
5
6
7
8
9
10
  • iterate

在 Stream API中,iterate()返回以initialValue(第一個(gè)參數(shù))開頭的元素流,匹配斷言(第二個(gè)參數(shù)),并使用第三個(gè)參數(shù)生成下一個(gè)元素。

static <T> Stream<T> iterate(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next)
jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
jshell> IntStream.iterate(2, x -> x < 20, x -> x * x).forEach(System.out::println)
2
4
16
 Java SE 9's iterate() = Java SE 8's iterate() + Java SE 8's filter()
jshell> IntStream.iterate(2, x -> x * x).filter(x -> x < 20).forEach(System.out::println)
2
4
16
  • ofNullable

在Stream API中,ofNullable()返回包含單個(gè)元素的順序流,如果非空,則返回一個(gè)空流。

jshell> Stream<Integer> s = Stream.ofNullable(1)
s ==> java.util.stream.ReferencePipeline$Head@1e965684

jshell> s.forEach(System.out::println)
1

jshell> Stream<Integer> s = Stream.ofNullable(null)
s ==> java.util.stream.ReferencePipeline$Head@3b088d51

jshell> s.forEach(System.out::println)

jshell> 

12、Enhanced @Deprecated annotation

在 Java SE 8 和更早版本上,@Deprecated 注解只是一個(gè)沒有任何方法的標(biāo)記類接口。它的作用是標(biāo)記一個(gè) Java API,可以是 calss,field,method,interface,constructor 等。
注釋@Deprecated可以標(biāo)記Java API。注釋@Deprecated有很多種含義,例如它可以表示在不遠(yuǎn)的將來的某個(gè)時(shí)間,被標(biāo)記的API將會(huì)被移除。它也可以表示這個(gè)API已經(jīng)被破壞了,并不應(yīng)該再被使用。它還有其它很多含義。為了提供更多有關(guān)@Deprecated的信息,@Deprecated添加了forRemoval元素和since元素。
Java SE 9 中也提供了掃描jar文件的工具jdeprscan。這款工具也可以掃描一個(gè)聚合類,這個(gè)類使用了Java SE中的已廢棄的API元素。 這個(gè)工具將會(huì)對(duì)使用已經(jīng)編譯好的庫的應(yīng)用程序有幫助,這樣使用者就不知道這個(gè)已經(jīng)編譯好的庫中使用了那些已廢棄的API。

13、HTTP 2 Client

在 Java SE 9 中,Oracle 公司將發(fā)布新的 HTTP 2 Client API 來支持 HTTP/2 協(xié)議和 WebSocket 特性。現(xiàn)有的 HTTP Client API 存在很多問題(如支持 HTTP/1.1 協(xié)議但是不支持 HTTP/2 協(xié)議和 WebSocket,僅僅作用在 Blocking 模式中,并存在大量性能問題),他們正在被使用新的 HTTP 客戶端的 HttpURLConnection API 所替代。
Oracle 公司準(zhǔn)備在 “java.net.http” 包下引入新的 HTTP 2 Client API。它將同時(shí)支持 HTTP/1.1 和 HTTP/2 協(xié)議,也同時(shí)支持同步(Blocking Mode)和異步模式,支持 WebSocket API 使用中的異步模式。

jshell> import java.net.http.*

jshell> import static java.net.http.HttpRequest.*

jshell> import static java.net.http.HttpResponse.*

jshell> URI uri = new URI("http://rams4java.blogspot.co.uk/2016/05/java-news.html")
uri ==> http://rams4java.blogspot.co.uk/2016/05/java-news.html

jshell> HttpResponse response = HttpRequest.create(uri).body(noBody()).GET().response()
response ==> java.net.http.HttpResponseImpl@79efed2d

jshell> System.out.println("Response was " + response.body(asString()))

14、Мulti-Resolution Image API

在 Java SE 9 中,Oracle 公司將引入一個(gè)新的 Мulti-Resolution Image API。這個(gè) API 中比較重要的接口是 MultiResolutionImage,在 java.awt.image 包下可獲取到。
MultiResolutionImage 封裝不同高度和寬度圖片(不同解決方案)到一個(gè)集合中,并允許我們按需查詢使用

15、Miscellaneous Java 9 Features

  • GC增強(qiáng)
  • 統(tǒng)一的JVM日志
  • HTML5風(fēng)格的Java幫助文檔
  • 保留下劃線字符。變量不能被命名為_;
  • 廢棄Applet API;
  • javac不再支持Java1.4以及之前的版本;
  • 廢棄Java瀏覽器插件;
  • 棧遍歷API–棧遍歷API能過濾和遲訪問在堆
  • 棧跟蹤中的信息
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,837評(píng)論 18 139
  • Java9 新特性 翻譯自 : https://docs.oracle.com/javase/9/whatsnew...
    deadoggy閱讀 1,298評(píng)論 0 2
  • 作者介紹 菲比 .吉爾曼 (Phoebe Gilman)生于美國紐約,曾在紐約、以色列和歐洲學(xué)習(xí)藝術(shù)創(chuàng)作,現(xiàn)定居加...
    發(fā)芽的夢(mèng)閱讀 3,117評(píng)論 0 1
  • 那年夏天 遇見你 齊肩短發(fā)女孩 你的笑容燦爛 我們一見如故 那年夏天 遇見你 同桌的你 教我復(fù)雜難解的數(shù)學(xué)題 我們...
    書南Q閱讀 327評(píng)論 6 9
  • 我在那兒等你, 等你等到天明。 不是夜太短, 是對(duì)你的思念,太長(zhǎng)…… 就這樣,一直等你, 秋風(fēng)把夏天的汗水,風(fēng)干……
    小劇在成長(zhǎng)閱讀 186評(píng)論 0 6