Java 9 New Features

Java 9 概述

1. jdk 9 的發佈、通過 4 次跳票,歷經曲折的 java 9 終於終於在 2017 年 9 月 21 日發佈。html

2. Java 9 中哪些不得不說的新特性?
java 9 提供了超過 150 項新功能特性,包括備受期待的模塊化系統、可交互的 REPL 工具:jshell,JDK 編譯工具,Java 公共 API 和私有代碼,以及安全加強、擴展提高、性能管理改善等。能夠說 Java 9 是一個龐大的系統工程,徹底作了一個總體改變。
具體來說:java

 模塊化系統
 jShell 命令
 多版本兼容 jar 包
 接口的私有方法
 鑽石操做符的使用升級
 語法改進:try 語句
 下劃線使用限制
 String 存儲結構變動
 便利的集合特性:of()
 加強的 Stream API
 多分辨率圖像 API
 全新的 HTTP 客戶端 API
 Deprecated 的相關 API
 智能 Java 編譯工具
 統一的 JVM 日誌系統
 javadoc 的 HTML 5 支持
 Javascript 引擎升級:Nashorn
 java 的動態編譯器

3. java 語言後續版本的更迭從Java 9 這個版本開始,Java 的計劃發佈週期是 6 個月,下一個 Java 的主版本將於 2018 年 3 月發佈,命名爲 Java 18.3,緊接着再過六個月將發佈 Java 18.9。
這意味着java的更新從傳統的以特性驅動的發佈週期,轉變爲以時間驅動的(6 個月爲週期)發佈模式,並逐步的將 Oracle JDK 原商業特性進行開源。
針對企業客戶的需求,Oracle 將以三年爲週期發佈長期支持版本(long term support)。
4. 如何看待 java 9 的更新
Java 更快的發佈週期意味着開發者將不須要像之前同樣爲主要發佈版本望眼欲穿。這也意味着開發者將可能跳過 Java 9 和它的不成熟的模塊化功能,只須要再等待 6 個月就能夠迎來新版本,這將可能解決開發者的糾結。
oracle 理念
與 小步快跑,快速迭代c++

java 9 的安裝和官網說明

1.jdk 9 的下載下載安裝完畢,須要配置環境變量:git

1 新建 JAVA_HOME 的環境變量,變量值爲 jdk 路徑。以下:github

2 將 JAVA_HOME 配置到 path 環境變量下:
算法

以後在命令行校驗是否配置成功。成功,則顯示以下:shell

2. java 9 幫助文檔的下載

3.在線 Oracle JDK 9 Documentation編程

Java 9 的新特性

官方提供的新特性列表
或參考 Open JDK

特性
Featuresapi

JEP 102: Process API Updates
JEP 110: HTTP 2 Client
JEP 143: Improve Contended Locking
JEP 158: Unified JVM Logging
JEP 165: Compiler Control
JEP 193: Variable Handles
JEP 197: Segmented Code Cache
JEP 199: Smart Java Compilation, Phase Two
JEP 200: The Modular JDK
JEP 201: Modular Source Code
JEP 211: Elide Deprecation Warnings on Import Statements
JEP 212: Resolve Lint and Doclint Warnings
JEP 213: Milling Project Coin
JEP 214: Remove GC Combinations Deprecated in JDK 8
JEP 215: Tiered Attribution for javac
JEP 216: Process Import Statements Correctly
JEP 217: Annotations Pipeline 2.0
JEP 219: Datagram Transport Layer Security (DTLS)
JEP 220: Modular Run-Time Images
JEP 221: Simplified Doclet API
JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)
JEP 223: New Version-String Scheme
JEP 224: HTML5 Javadoc
JEP 225: Javadoc Search
JEP 226: UTF-8 Property Files
JEP 227: Unicode 7.0
View Code
102:API 更新過程
110:2 HTTP 客戶端
143:改善競爭鎖
158:統一 JVM 日誌記錄
165:編譯器控制
193:變量處理
197:分段代碼緩存
199:聰明的 Java 編譯,第二階段
200:模塊化 JDK
201:模塊化的源代碼
211: 導入語句時省略警告信息
212:解決 Lint 和 Doclint 警告
213:研磨項目 Coin
214:移除 JDK 8 過期的 GC 組合
215:javac 分層歸因
216:正確處理導入語句
217:2.0 註釋管道
219:數據報傳輸層安全性(DTLS)
220:模塊化運行時圖像
221:簡化 Doclet API
222:jshell:Java Shell(Read-Eval-Print-Loop)
223: 字符串新版本方案
224:Javadoc 支持 HTML5
225:Javadoc 搜索
226:utf - 8 屬性文件
227:Unicode 7.0
JEP 228: Add More Diagnostic Commands 228:添加更多的診斷命令
JEP 229: Create PKCS12 Keystores by Default 229:建立 PKCS12 默認密鑰存儲庫
JEP 231: Remove Launch-Time JRE Version Selection 231:刪除啓動 JRE 版本選擇
JEP 232: Improve Secure Application Performance 232:提升安全應用程序性能
JEP 233: Generate Run-Time Compiler Tests Automatically 233:自動生成運行時編譯器測試
JEP 235: Test Class-File Attributes Generated by javac 235:測試 javac 生成的類文件屬性
JEP 236: Parser API for Nashorn 236:Nashorn 解析器 API
JEP 237: Linux/AArch64 Port 237:Linux / AArch64 端口
JEP 238: Multi-Release JAR Files 238:Multi-Release JAR 文件
JEP 240: Remove the JVM TI hprof Agent 240:刪除 JVM TI hprof 代理
JEP 241: Remove the jhat Tool 241:刪除 jhat 工具
JEP 243: Java-Level JVM Compiler Interface 243:java 級別 JVM 編譯器接口
JEP 244: TLS Application-Layer Protocol Negotiation Extension 244:TLS 應用層協議談判擴展
JEP 245: Validate JVM Command-Line Flag Arguments 245:JVM 命令行標記參數進行驗證
JEP 246: Leverage CPU Instructions for GHASH and RSA 246:利用 CPU 指令 GHASH 和 RSA
JEP 247: Compile for Older Platform Versions 247:老平臺版本編譯
JEP 248: Make G1 the Default Garbage Collector 248:設置 G1 爲默認的垃圾收集器
JEP 249: OCSP Stapling for TLS 249:OCSP 裝訂 TLS
JEP 250: Store Interned Strings in CDS Archives 250:CDS 檔案中存儲實際字符串
JEP 251: Multi-Resolution Images 251:多分辨率圖像
JEP 252: Use CLDR Locale Data by Default 252:使用系統默認語言環境數據
JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization 253 年:準備 JavaFX UI 控件和 CSS api 用於模塊化
JEP 254: Compact Strings 254:緊湊的字符串
JEP 255: Merge Selected Xerces 2.11.0 Updates into JAXP 255:合併選定的 Xerces 2.11.0 更新到 JAXP
JEP 256: BeanInfo Annotations 256:BeanInfo 註釋
JEP 257: Update JavaFX/Media to Newer Version of GStreamer 257:更新 JavaFX /Media 到 GStreamer 的新版本
JEP 258: HarfBuzz Font-Layout Engine 258:HarfBuzz 文字編排引擎
JEP 259: Stack-Walking API 259:提供 Stack – Walking API
JEP 260: Encapsulate Most Internal APIs 260:封裝內部 api
JEP 261: Module System 261:模塊系統
JEP 262: TIFF Image I/O 262:TIFF 圖像 I/O
JEP 263: HiDPI Graphics on Windows and Linux 263:Windows 和 Linux 上的 HiDPI 圖形
JEP 264: Platform Logging API and Service 264:日誌 API 和服務平臺
JEP 265: Marlin Graphics Renderer 265:Marlin 圖形渲染器
JEP 266: More Concurrency Updates 266:更多的併發更新
JEP 267: Unicode 8.0 267:Unicode 8.0
JEP 268: XML Catalogs 268:XML 目錄
JEP 269: Convenience Factory Methods for Collections 269:方便的集合工廠方法
JEP 270: Reserved Stack Areas for Critical Sections 270:保留堆棧領域相當重要的部分
JEP 271: Unified GC Logging 271:統一的 GC 日誌記錄
JEP 272: Platform-Specific Desktop Features 272:特定於平臺的桌面功能
JEP 273: DRBG-Based SecureRandom Implementations 273:基於 DRBG 的 SecureRandom 實現
JEP 274: Enhanced Method Handles 274:加強的方法處理
JEP 275: Modular Java Application Packaging 275:模塊化 Java 應用程序包裝
JEP 276: Dynamic Linking of Language-Defined Object Models 276:語言定義對象模型的動態連接
JEP 277: Enhanced Deprecation 277:加強的棄用
JEP 278: Additional Tests for Humongous Objects in G1 278:爲 G1 的極大對象提供額外的測試
JEP 279: Improve Test-Failure Troubleshooting 279:改善測試失敗的故障排除
JEP 280: Indify String Concatenation 280:Indify 字符串鏈接
JEP 281: HotSpot C++ Unit-Test Framework 281:熱點 c++的單元測試框架
JEP 282: jlink: The Java Linker 282:jlink:Java 鏈接器
JEP 283: Enable GTK 3 on Linux 283:在 Linux 上啓用 GTK 3
JEP 284: New HotSpot Build System 284:新熱點的構建系統
JEP 285: Spin-Wait Hints 285:循環等待提示
JEP 287: SHA-3 Hash Algorithms 287:SHA-3 散列算法
JEP 288: Disable SHA-1 Certificates 288:禁用 sha - 1 證書
JEP 289: Deprecate the Applet API 289:標記過期的 Applet API
JEP 290: Filter Incoming Serialization Data 290:過濾傳入的序列化數據
291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector 291:反對併發標記清理垃圾收集器(CMS)
JEP 292: Implement Selected ECMAScript 6 Features in Nashorn 292:實現選定的 ECMAScript Nashorn 6 特性
JEP 294: Linux/s390x Port 294:Linux / s390x 端口
JEP 295: Ahead-of-Time Compilation 295:提早編譯
JEP 297: Unified arm32/arm64 Port 297:統一的 arm32 / arm64 端口
JEP 298: Remove Demos and Samples 298:刪除演示和樣本
JEP 299: Reorganize Documentation 299:整理文檔
JEP(JDK Enhancement Proposals):jdk 改進提案,每當須要有新的設想時候, JEP 能夠在 JCP(java community Process)以前或者同時提出非正式的規範(specification),被正式承認的 JEP 正式寫進 JDK 的發展路線圖並分配版本號。
JSR(Java Specification Requests):java 規範提案,新特性的規範出如今這一階段,是指向 JCP(Java Community Process)提出新增一個標準化技術規範的正式請求。請求能夠來自於小組/項目、 JEP、 JCP成員或者 java 社區(community)成員的提案,每一個 java 版本都由相應的 JSR 支持。
小組:對特定技術內容,好比安全、網絡、HotSpot 等有共同興趣的組織和我的
項目:編寫代碼、文檔以及其餘工做,至少由一個小組贊助和支持,好比最近的 Lambda 計劃,JigSaw 計劃等
View Code

1. JDK 和 JRE 的改變

1.1 JDK 與 JRE 的關係
JDK : Java Development Kit (Java 開發工具包)
JRE : Java Runtime Environment (Java 運行環境)瀏覽器

說明:
JDK = JRE + 開發工具集(例如 Javac 編譯工具等)
JRE = JVM + Java SE 標準類庫
1.2 JDK 8 的目錄結構

說明:

1.3 JDK 9 的目錄結構

說明:

2. 模塊化系統:

Jigsaw =>Modularity

 

2.1 官方 Feature

200: The Modular JDK
201: Modular Source Code
220: Modular Run-Time Images
260: Encapsulate Most Internal APIs
261: Module System
282: jlink: The Java Linker

2.2 產生背景及意義

談到 Java 9 你們每每第一個想到的就是 Jigsaw 項目。衆所周知,Java 已經發展超過 20 年(95 年最初發布),Java 和相關生態在不斷豐富的同時也愈來愈暴露出一些問題:
Java 運行環境的膨脹和臃腫。每次JVM啓動的時候,至少會有30~60MB的內存加載,主要緣由是JVM須要加載rt.jar,無論其中的類是否被classloader加載,第一步整個jar都會被JVM加載到內存當中去(而模塊化能夠根據模塊的須要加載程序運行須要的class)
當代碼庫愈來愈大,建立複雜,盤根錯節的「意大利麪條式代碼」的概率呈指數級的增加。不一樣版本的類庫交叉依賴致使讓人頭疼的問題,這些都阻礙了 Java 開發和運行效率的提高。很難真正地對代碼進行封裝, 而系統並無對不一樣部分(也就是 JAR 文件)之間的依賴關係有個明確的概念。每個公共類均可以被類路徑之下任何其它的公共類所訪問到,這樣就會致使無心中使用了並不想被公開訪問的 API。

類路徑自己也存在問題:

你怎麼知曉全部須要的 JAR 都已經有了, 或者是否是會有重複的項呢?
同時,因爲兼容性等各方面的掣肘,對 Java 進行大刀闊斧的革新愈來愈困難,Jigsaw 從 Java 7 階段就開始籌備,Java 8 階段進行了大量工做,終於在 Java 9 裏落地,一種千呼萬喚始出來的意味。
Jigsaw項目(後期改名爲Modularity)的工做量和難度大大超出了
初始規劃。JSR 376 Java 平臺模塊化系統(JPMS, Java Platform
Module System)做爲 Jigsaw 項目的核心, 其主體部分被分解成
6 個 JEP(JDK Enhancement Proposals)。
做爲java 9 平臺最大的一個特性,隨着 Java 平臺模塊化系統的落
地,開發人員無需再爲不斷膨脹的 Java 平臺苦惱,例如,您可
以使用 jlink 工具,根據須要定製運行時環境。這對於擁有大量
鏡像的容器應用場景或複雜依賴關係的大型應用等,都具備很是
重要的意義。
本質上講,模塊(module)的概念,其實就是package外再裹一層,
也就是說,
用模塊來管理各個package,經過聲明某個package暴露,
不聲明默認就是隱藏。所以,模塊化使得代碼組織上更安全,因
爲它能夠指定哪些部分能夠暴露,哪些部分隱藏。

2.3 設計理念

模塊獨立、化繁爲簡
模塊化(以 Java 平臺模塊系統的形式)將 JDK 分紅一組模塊,能夠在編譯時,運行時或者構建時進行組合。
2.4 實現目標
主要目的在於減小內存的開銷只須必要模塊,而非所有jdk模塊,可簡化各類類庫和大型應用的開發和維護改進 Java SE 平臺,使其能夠適應不一樣大小的計算設備改進其安全性,可維護性,提升性能
2.5 使用舉例

注: IntelliJ IDEA 2017.3 支持模塊化特性,這裏選擇此開發環境。
模塊將由一般的類和新的模塊聲明文件(module-info.java)組成。
該文件是位於 java 代碼結構的頂層,該模塊描述符明確地定義了咱們的模塊須要什麼依賴關係,以及哪些模塊被外部使用。在 exports 子句中未說起的全部包默認狀況下將封裝在模塊中,不能在外部使用。
java 9demo 模塊中的 ModuleTest 類使用以下:

public class ModuleTest {
private static final Logger LOGGER =Logger.getLogger("java9test");
public static void main(String[] args) {
    Person p = new Person("馬雲",40);
    System.out.println(p);
   }
}
LOGGER.info("aaaaaa");
@Test
public void test1(){
System.out.println("hello");
}
對應在 java 9demo 模塊的 src 下建立 module-info.java 文件:
module java9demo {
requires java9test;
requires java.logging;
requires junit;
}    

requires:指明對其它模塊的依賴。
在 java9test 模塊的指定包下提供類 Person:

public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
}
this.name = name;
this.age = age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
}
return age;
public void setAge(int age) {
this.age = age;
}
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
Person.java

 

要想在 java9demo 模塊中調用 java9test 模塊下包中的結構,須要在
java9test 的 module-info.java 中聲明:

module java9test {
//package we export
exports com.atguigu.bean;
}

exports:控制着哪些包能夠被其它模塊訪問到。全部不被導出的包
默認都被封裝在模塊裏面。
2.6 補充說明
關於更多 Java 9 模塊編程的內容請參考一本書:《Java 9 Modularity》
裏面講的比較詳細,介紹了當前 Java 對 jar 之間以來的管理是多麼的
混亂,引入 modularity 以後的改變會是很明顯的差異。
3. Java 的 REPL 工具: jShell 命令
3.1 官方 Feature
222: jshell: The Java Shell (Read-Eval-Print Loop)
3.2 產生背景

像 Python 和 Scala 之類的語言早就有交互式編程環境 REPL (read -
evaluate - print - loop)了,以交互式的方式對語句和表達式進行求值。
開發者只須要輸入一些代碼,就能夠在編譯前得到對程序的反饋。而
以前的 Java 版本要想執行代碼,必須建立文件、聲明類、提供測試
方法方可實現。

3.3 設計理念

即寫即得、快速運行

3.4 實現目標

Java 9 中終於擁有了 REPL 工具:jShell。利用 jShell 在沒有建立類的狀況下直接聲明變量,計算表達式,執行語句。即開發時能夠在命令行裏直接運行 java 的代碼,而無需建立 Java 文件,無需跟人解釋」public static void main(String[] args)」這句廢話。

 jShell 也能夠從文件中加載語句或者將語句保存到文件中。
 jShell 也能夠是 tab 鍵進行自動補全和自動添加分號。

3.5 使用舉例
調出 jShell

獲取幫助

基本使用

   

   

Tips:在 JShell 環境下,語句末尾的「;」 是可選的。但推薦仍是最好加上。提升代碼可讀性。
導入指定的包

默認已經導入以下的全部包:(包含 java.lang 包)

只需按下 Tab 鍵,就能自動補全代碼

列出當前 session 裏全部有效的代碼片斷

查看當前 session 下全部建立過的變量

查看當前 session 下全部建立過的方法

Tips:咱們還能夠從新定義相同方法名和參數列表的方法,即爲對現有方法的修改(或覆蓋)。
使用外部代碼編輯器來編寫 Java 代碼

從外部文件加載源代碼
指定目錄下提供 HelloWorld.java 文件:

public void printHello() {
System.out.println("立刻 2018 年了,尚硅谷祝全部的穀粉元旦
快樂!");
}
printHello();

使用/open 命令調用:

沒有受檢異常(編譯時異常)
說明:原本應該強迫咱們捕獲一個 IOException,但卻沒有出現。由於
jShell 在後臺爲咱們隱藏了。
退出 jShell

4. 多版本兼容 jar 包
4.1 官方 Feature
238: Multi-Release JAR Files
4.2 使用說明
當一個新版本的 Java 出現的時候,你的庫用戶要花費數年時間纔會
切換到這個新的版本。這就意味着庫得去向後兼容你想要支持的最老
的 Java 版本(許多狀況下就是 Java 6 或者 Java7)。這實際上意味着
將來的很長一段時間,你都不能在庫中運用 Java 9 所提供的新特性。
幸運的是,多版本兼容 jar 功能能讓你建立僅在特定版本的 Java 環境
中運行庫程序選擇使用的 class 版本。
舉例 1:

jar root
  - A.class
  - B.class
  - C.class
  - D.class
  - META-INF
     - versions
       - 9
         - A.class
         - B.class

說明:
在上述場景中, root.jar 能夠在 Java 9 中使用, 不過 A 或 B 類使用的不是頂層的root.A 或 root.B 這 兩 個 class, 而 是 處 在「META-INF/versions/9」下面的這兩個。這是特別爲 Java 9 準備的class 版本,能夠運用 Java 9 所提供的特性和庫。同時,在早期的 Java諸版本中使用這個 JAR 也是能運行的,由於較老版本的 Java 只會看到頂層的 A 類或 B 類。
舉例 2:

jar root
   - A.class
   - B.class
   - C.class
   - D.class
   - META-INF
       - versions
          - 9
             - A.class
             - B.class
          - 10
             - A.class

官方說明:
By this scheme, it is possible for versions of a class designed for a later  Java platform release to override the version of that same class designed  for an earlier Java platform release.
4.3 使用舉例
步驟一:提供必要的類
在指定目錄(E:\teach\01_Java9\multijar\src\main\java\com\atguigu)下
提供以下的類:
【Generator.java】

package com.atguigu;
import java.util.Set;
import java.util.HashSet;
/**
* Created by songhongkang on 2017/12/28 0028.
*/
public class Generator {
}
public Set<String> createStrings() {
Set<String> strings = new HashSet<String>();
strings.add("Java");
strings.add("8");
return strings;
}
Generator.java

【Application.java】

package com.atguigu;
import com.atguigu.Generator;
import
import
import
import
java.io.IOException;
java.util.List;
java.util.ArrayList;
java.util.Set;
/**
* Created by songhongkang on 2017/12/28 0028.
*/
public class Application {
public static void testMultiJar() {
com.atguigu.Generator gen = new Generator();
System.out.println("Generated strings: " +
gen.createStrings());
}
}
Application.java

在 如 下 目 錄 (E:\teach\01_Java9\multijar\src\main\java-9\com\atguigu)
下提供同名的類:
【Generator.java】

package com.atguigu;
import java.util.Set;
/**
* Created by songhongkang on 2017/12/28 0028.
*/
public class Generator {
}
public Set<String> createStrings() {
return Set.of("Java", "9");
}
Generator.java

步驟二:打包
指令以下:

javac -d build --release 8 src/main/java/com/atguigu/*.java
javac -d build9 --release 9 src/main/java-9/com/atguigu/*.java
jar --create --main-class=Application --file multijar.jar -C build . --release 9 -C build9 .

步驟三:在 java 9 及以前版本的環境下進行測試便可
5. 語法改進:接口的私有方法
5.1 官方 Feature
213: Milling Project Coin Support for private methods in interfaces was briefly in consideration for inclusion in Java SE 8 as part of the effort to add support for Lambda  Expressions, but was withdrawn to enable better focus on higher priority  tasks for Java SE 8. It is now proposed that support for private interface   methods be undertaken thereby enabling non abstract methods of an   interface to share code between them.
5.2 使用說明
Java 8 中規定接口中的方法除了抽象方法以外,還能夠定義靜態 方法和默認的方法。必定程度上,擴展了接口的功能,此時的接口更像是一個抽象類。
在 Java 9 中,接口更加的靈活和強大,連方法的訪問權限修飾符均可以聲明爲 private 的了,此時方法將不會成爲你對外暴露的 API的一部分。
5.3 使用舉例

/**
* Created by songhongkang
*/
interface MyInterface {
void normalInterfaceMethod();
default void methodDefault1() {
init();
}
public default void methodDefault2() {
init();
}
// This method is not part of the public API exposed by
MyInterface
private void init() {
System.out.println("默認方法中的通用操做");
}
}
class MyInterfaceImpl implements MyInterface{
@Override
public void normalInterfaceMethod() {
System.out.println("實現接口的方法");
}
}
public class MyInterfaceTest{
public static void main(String[] args) {
MyInterfaceImpl impl = new MyInterfaceImpl();
impl.methodDefault1();
//
}
impl.init();// 不能調用
}
MyInterface.java

6. 語法改進:鑽石操做符(Diamond Operator)使用升級

6.1 使用說明
咱們將可以與匿名實現類共同使用鑽石操做符(diamond operator)在 java 8 中以下的操做是會報錯的:

private List<String> flattenStrings(List<String>... lists) {
}
Set<String> set = new HashSet<>(){};
for(List<String> list : lists) {
set.addAll(list);
}
return new ArrayList<>(set);

編譯報錯信息: '<>' cannot be used with anonymous classes
6.2 使用舉例

private List<String> flattenStrings(List<String>... lists) {
// anonymous classes can now use type inference
Set<String> set = new HashSet<>(){};
for(List<String> list : lists) {
set.addAll(list);
}
return new ArrayList<>(set);
}
View Code

7. 語法改進:try 語句
7.1 使用舉例
在 java 8 以前,咱們習慣於這樣處理資源的關閉:

InputStreamReader reader = null;
try{
    reader = new InputStreamReader(System.in);
   // 流的操做
    reader.read();
  }catch (IOException e){
         e.printStackTrace();
    }finally{
     if(reader != null){
try {
      reader.close();
} catch (IOException e) {
            e.printStackTrace();
        }
    }
}    
View Code

java 8 中,能夠實現資源的自動關閉,可是要求執行後必須關閉的所
有資源必須在 try 子句中初始化,不然編譯不經過。以下例所示:

try(InputStreamReader reader = new
InputStreamReader(System.in)){
}catch (IOException e){
e.printStackTrace();
}
View Code

java 9 中,用資源語句編寫 try 將更容易,咱們能夠在 try 子句中使用
已經初始化過的資源,此時的資源是 final 的:

InputStreamReader reader = new InputStreamReader(System.in);
OutputStreamWriter writer = new OutputStreamWriter(System.out);
try(reader;writer){
//reader 是 final 的,不可再被賦值
//
reader = null;
}catch (IOException e){
e.printStackTrace();
}
View Code

8. 語法改進:UnderScore(下劃線)使用的限制

8.1 使用說明
在 java 8 中,標識符能夠獨立使用「_」來命名:
String _ = "hello";
System.out.println(_);
可是,在 java 9 中規定「_」再也不能夠單獨命名標識符了,若是使用,會報錯:
9. String 存儲結構變動
9.1 官方 Feature
JEP 254: Compact Strings
9.2 產生背景

Motivation
The current implementation of the String class stores characters in
a char array, using two bytes (sixteen bits) for each character. Data
gathered from many different applications indicates that strings are a
major component of heap usage and, moreover, that most String
objects contain only Latin-1 characters. Such characters require only
one byte of storage, hence half of the space in the internal char arrays
of such String objects is going unused.

9.3 使用說明

Description
We propose to change the internal representation of the String class
from a UTF-16 char array to a byte array plus an encoding-flag
field. The new String class will store characters encoded either as
ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes
per character), based upon the contents of the string. The encoding
flag will indicate which encoding is used.

結論:String 不再用 char[] 來存儲啦,改爲了 byte[] 加上編碼標
記,節約了一些空間。

public final class String
implements java.io.Serializable, Comparable<String>,
CharSequence {
@Stable
private final byte[] value;

9.4 拓展:StringBuffer 與 StringBuilder
那 StringBuffer 和 StringBuilder 是否仍無動於衷呢?

String-related classes such as AbstractStringBuilder, StringBuilder,
and StringBuffer will be updated to use the same representation, as
will the HotSpot VM's intrinsic string operations.

10. 集合工廠方法:快速建立只讀集合

10.1 官方 Feature
269: Convenience Factory Methods for Collections
10.2 產生背景
要建立一個只讀、不可改變的集合,必須構造和分配它,而後添加元
素,最後包裝成一個不可修改的集合。
好比:

List<String> namesList = new ArrayList <>();
namesList.add("Joe");
namesList.add("Bob");
namesList.add("Bill");
namesList = Collections.unmodifiableList(namesList);
System.out.println(namesList);

缺點:咱們一下寫了五行。即:它不能表達爲單個表達式。
固然,咱們也能夠稍微簡單點處理:

List<String> list =Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
Set<String> set = Collections.unmodifiableSet(new
HashSet<>(Arrays.asList("a", "b", "c")));
// 以下操做不適用於 jdk 8 及以前版本,適用於 jdk 9
Map<String,Integer> map = Collections.unmodifiableMap(new
HashMap<>(){
{
put("a", 1);
put("b", 2);
put("c", 3);
}
});
map.forEach((k,v) -> System.out.println(k + ":" + v));

10.3 使用說明
Java 9 所以引入了方便的方法,這使得相似的事情更容易表達。

List firsnamesList = List.of(「Joe」,」Bob」,」Bill」);調用集合中靜態方法 of(),能夠將不一樣數量的參數傳輸到此工廠方法中。此功能可用於 Set 和 List,也可用於 Map 的相似形式。此時獲得的集合,是不可變的:在建立後,繼續添加元素到這些集合會致使「UnsupportedOperationException」 。因爲 Java 8 中接口方法的實現,能夠直接在 List,Set 和 Map 的接口內定義這些方法,便於調用。
10.4 使用舉例

List<String> list = List.of("a", "b", "c");
Set<String> set = Set.of("a", "b", "c");
Map<String, Integer> map1 = Map.of("Tom", 12, "Jerry", 21,
"Lilei", 33, "HanMeimei", 18);
Map<String, Integer> map2 = Map.ofEntries(
Map.entry("Tom", 89),
Map.entry("Jim", 78),
Map.entry("Tim", 98)
);

11. 加強的 Stream API

11.1 使用說明
Java 的 Steam API 是java標準庫最好的改進之一,讓開發者可以快速運算,從而可以有效的利用數據並行計算。Java 8 提供的 Steam可以利用多核架構實現聲明式的數據處理。
在 Java 9 中, Stream API 變得更好, Stream 接口中添加了 4 個新的方法:dropWhile, takeWhile, ofNullable,還有個 iterate 方法的新重載方法,可讓你提供一個 Predicate (判斷條件)來指定何時結束迭代。(見下例)
除了對 Stream 自己的擴展,Optional 和 Stream 之間的結合也獲得了改進。如今能夠經過 Optional 的新方法 stream() 將一個Optional 對象轉換爲一個(多是空的) Stream 對象。(見下例)
11.2 使用舉例
takeWhile()的使用:
用於從 Stream 中獲取一部分數據,接收一個 Predicate 來進行選擇。在有序的
Stream 中,takeWhile 返回從開頭開始的儘可能多的元素。

List<Integer> list =Arrays.asList(45,43,76,87,42,77,90,73,67,88);
list.stream().takeWhile(x -> x < 50)
.forEach(System.out::println);
System.out.println();
list = Arrays.asList(1,2,3,4,5,6,7,8);
list.stream().takeWhile(x -> x < 5)
.forEach(System.out::println);

dropWhile()的使用:
dropWhile 的行爲與 takeWhile 相反,返回剩餘的元素。

List<Integer> list =Arrays.asList(45,43,76,87,42,77,90,73,67,88);
list.stream().dropWhile(x -> x < 50)
.forEach(System.out::println);
System.out.println();
list = Arrays.asList(1,2,3,4,5,6,7,8);
list.stream().dropWhile(x -> x < 5)
.forEach(System.out::println);

ofNullable()的使用:
Java 8 中 Stream 不能徹底爲 null,不然會報空指針異常。而 Java 9 中的
ofNullable 方法容許咱們建立一個單元素 Stream,能夠包含一個非空元素,也可
以建立一個空 Stream。

// 報 NullPointerException
//Stream<Object> stream1 = Stream.of(null);
//System.out.println(stream1.count());
// 不報異常,容許經過
Stream<String> stringStream = Stream.of("AA", "BB", null);
System.out.println(stringStream.count());//3
// 不報異常,容許經過
List<String> list = new ArrayList<>();
list.add("AA");
list.add(null);
System.out.println(list.stream().count());//2
//ofNullable() :容許值爲 null
Stream<Object> stream1 = Stream.ofNullable(null);
System.out.println(stream1.count());//0
Stream<String> stream = Stream.ofNullable("hello world");
System.out.println(stream.count());//1

iterator()重載的使用:
原來的控制終止方式:

Stream.iterate(1,i -> i + 1).limit(10)
.forEach(System.out::println);

如今的終止方式:

Stream.iterate(1,i -> i < 100,i -> i + 1)
.forEach(System.out::println);
Optional 類中 stream()的使用:
List<String> list = new ArrayList<>();
list.add("Tom");
list.add("Jerry");
list.add("Tim");
Optional<List<String>> optional =
Optional.ofNullable(list);
Stream<List<String>> stream = optional.stream();
stream.flatMap(x ->
x.stream()).forEach(System.out::println);

12. 多分辨率圖像 API

12.1 官方 Feature
251: Multi-Resolution Images
263: HiDPI Graphics on Windows and Linux
12.2 產生背景

在 Mac 上, JDK 已經支持視網膜顯示,但在 Linux 和 Windows 上,
它並無。在那裏,Java 程序在當前的高分辨率屏幕上可能看起來很
小,不能使用它們。這是由於像素用於這些系統的大小計算(不管像
素實際有多大)。畢竟,高分辨率顯示器的有效部分是像素很是小。
JEP 263 以這樣的方式擴展了 JDK,即 Windows 和 Linux 也考慮到
像素的大小。爲此,使用比如今更多的現代 API: Direct2D for Windows
和 GTK +,而不是 Xlib for Linux。圖形,窗口和文本由此自動縮放。
JEP 251 還提供處理多分辨率圖像的能力,即包含不一樣分辨率的
相同圖像的文件。根據相應屏幕的 DPI 度量,而後以適當的分辨率使
用圖像。
View Code

12.3 使用說明
新的 API 定義在 java.awt.image 包下
將不一樣分辨率的圖像封裝到一張(多分辨率的)圖像中,做爲它的變體
獲取這個圖像的全部變體
獲取特定分辨率的圖像變體-表示一張已知分辨率單位爲 DPI 的特定尺寸大小的邏輯圖像,而且這張圖像是最佳的變體。
基於當前屏幕分辨率大小和運用的圖像轉換算法,java.awt.Graphics 類能夠從接口 MultiResolutionImage 獲取所需的變體。
MultiResolutionImage 的基礎實現是java.awt.image.BaseMultiResolutionImage。

13. 全新的 HTTP 客戶端 API

13.1 官方 Feature
110: HTTP 2 Client
13.2 使用說明

HTTP,用於傳輸網頁的協議,早在 1997 年就被採用在目前的 1.1版本中。直到 2015 年,HTTP2 才成爲標準。HTTP/1.1 和 HTTP/2 的主要區別是如何在客戶端和服務器之間構建和傳輸數據。HTTP/1.1 依賴於請求/響應週期。 HTTP/2 容許服務器「push」數據:它能夠發送比客戶端請求更多的數據。 這使得它能夠優先處理併發送對於首先加載網頁相當重要的數據。Java 9 中有新的方式來處理 HTTP 調用。它提供了一個新的 HTTP客 戶 端 ( HttpClient ), 它 將 替 代 僅 適 用 於 blocking 模 式 的HttpURLConnection (HttpURLConnection 是在 HTTP 1.0 的時代建立的,並使用了協議無關的方法),並提供對 WebSocket 和 HTTP/2 的支持。此外,HTTP 客戶端還提供 API 來處理 HTTP/2 的特性,好比流和
服務器推送等功能。全新的 HTTP 客戶端 API 能夠從 jdk.incubator.httpclient 模塊中獲取。由於在默認狀況下,這個模塊是不能根據 classpath 獲取的,須要使
用 add modules 命令選項配置這個模塊,將這個模塊添加到 classpath中。
View Code

13.3 使用舉例

HttpClient client = HttpClient.newHttpClient();
HttpRequest req =
HttpRequest.newBuilder(URI.create("http://www.atguigu.com"
))
.GET()
.build();
HttpResponse<String> response = client.send(req,
HttpResponse.BodyHandler.asString());
System.out.println(response.statusCode());
System.out.println(response.version().name());
System.out.println(response.body());
舉例

14. Deprecated 的相關 API

14.1 官方 Feature
211: Elide Deprecation Warnings on Import Statements
214: Remove GC Combinations Deprecated in JDK 8
277: Enhanced Deprecation
289: Deprecate the Applet API
291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector
14.2 使用說明

Java 9 廢棄或者移除了幾個不經常使用的功能。其中最主要的是Applet API,如今是標記爲廢棄的。隨着對安全要求的提升,主流瀏覽器已經取消對 Java 瀏覽器插件的支持。 HTML5 的出現也進一步加速了它的消亡。開發者如今可使用像 Java Web Start 這樣的技術來代替 Applet,它能夠實現從瀏覽器啓動應用程序或者安裝應用程序。同時,appletviewer 工具也被標記爲廢棄。

15. 智能 Java 編譯工具

15.1 官方 Feature
139: Enhance javac to Improve Build Speed.
199: Smart Java Compilation, Phase Two
15.2 使用說明
智能 java 編譯工具( sjavac )的第一個階段始於 JEP139 這個項目,
用於在多核處理器狀況下提高 JDK 的編譯速度。現在,這個項目已經
進入第二階段,即 JEP199,其目的是改進 Java 編譯工具,並取代目
前 JDK 編譯工具 javac,繼而成爲 Java 環境默認的通用的智能編譯工
具。
JDK 9 還更新了 javac 編譯器以便可以將 java 9 代碼編譯運行
在低版本 Java 中。

16. 統一的 JVM 日誌系統

16.1 官方 Feature
158: Unified JVM Logging
271: Unified GC Logging
16.2 使用說明

日誌是解決問題的惟一有效途徑:曾經很難知道致使 JVM 性能問題和致使 JVM 崩潰的根本緣由。不一樣的 JVM 日誌的碎片化和日誌
選項(例如:JVM 組件對於日誌使用的是不一樣的機制和規則),這使得 JVM 難以進行調試。解決該問題最佳方法:對全部的 JVM 組件引入一個單一的系統,這些 JVM 組件支持細粒度的和易配置的 JVM 日誌。

17. javadoc 的 HTML 5 支持

17.1 官方 Feature
224: HTML5 Javadoc
225: Javadoc Search
17.2 使用說明
jdk 8 :生成的 java 幫助文檔是在 HTML 4 中,而 HTML 4 已是好久的標準了。
jdk 9 :javadoc 的輸出,如今符合兼容 HTML 5 標準。下圖是 java8 中生成的 html 頁面,若是想要找到一些類文檔,必須在 google 中搜索。

下圖是在 java 9 中,添加了一個搜索框。

 

18. Javascript 引擎升級:Nashorn

18.1 官方 Feature
236: Parser API for Nashorn
292: Implement Selected ECMAScript 6 Features in Nashorn
18.2 使用說明

Nashorn 項目在 JDK 9 中獲得改進,它爲 Java 提供輕量級的
Javascript 運行時。Nashorn 項目跟隨 Netscape 的 Rhino 項目,目
的是爲了在 Java 中實現一個高性能但輕量級的 Javascript 運行時。
Nashorn 項目使得 Java 應用可以嵌入 Javascript。它在 JDK 8 中爲
Java 提供一個 Javascript 引擎。
JDK 9 包含一個用 來解析 Nashorn 的 ECMAScript 語法樹 的
API。這個 API 使得 IDE 和服務端框架不須要依賴 Nashorn 項目的
內部實現類,就可以分析 ECMAScript 代碼。

19. java 的動態編譯器

19.1 官方 Feature
243: Java-Level JVM Compiler Interface
295: Ahead-of-Time Compilation
19.2 產生背景

Oracle 一直在努力提升 Java 啓動和運行時性能,但願其可以在
更普遍的場景達到或接近本地語言的性能。可是,直到今天,談到
Java,不少 C/C++ 開發者仍是會不屑地評價爲啓動慢,吃內存。
簡單說,這主要是由於 Java 編譯產生的類文件是 Java 虛擬機
能夠理解的二進制代碼,而不是真正的可執行的本地代碼,須要 Java
虛擬機進行解釋和編譯,這帶來了額外的開銷。

19.3 使用說明

JIT(Just-in-time)編譯器能夠在運行時將熱點編譯成本地代碼,
速度很快。可是 Java 項目如今變得很大很複雜,所以 JIT 編譯器需
要花費較長時間才能熱身完,並且有些 Java 方法還無法編譯,性能
方面也會降低。AoT 編譯就是爲了解決這些問題而生的。
在 JDK 9 中, AOT(JEP 295: Ahead-of-Time Compilation)做爲實
驗特性被引入進來,開發者能夠利用新的 jaotc 工具將重點代碼轉換
成相似類庫同樣的文件。雖然仍處於試驗階段,但這個功能使得 Java
應用在被虛擬機啓動以前可以先將 Java 類編譯爲原生代碼。此功能
旨在改進小型和大型應用程序的啓動時間,同時對峯值性能的影響很小。
可是 Java 技術供應商 Excelsior 的營銷總監 Dmitry Leskov 擔
心 AoT 編譯技術不夠成熟,但願 Oracle 可以等到 Java 10 時有個更穩定版本才發佈。
另外 JVMCI (JEP 243: Java-Level JVM Compiler Interface)等特性,
對於整個編程語言的發展,可能都具備很是重要的意義,雖然未必引
起了普遍關注。目前 Graal Core API 已經被集成進入 Java 9,雖然還
只是初始一小步,可是徹底用 Java 語言來實現的可靠的、高性能的
動態編譯器,彷佛再也不是高不可攀,這是 Java 虛擬機開發工程師的福音。
與此同時,隨着 Truffle 框架和 Substrate VM 的發展,已經讓個
別信心滿滿的工程師高呼「One VM to Rule Them All!」, 也許就在不
遠的未來 Ploygot 以一種另類的方式成爲現實。 

總結

1.在 java 9 中看不到什麼?

1.1 一個標準化和輕量級的 JSON API一個標準化和輕量級的 JSON API 被許多 java 開發人員所青睞。可是因爲資金問題沒法在 Java 9 中見到,但並不會削減掉。Java 平臺首席架構師 Mark Reinhold 在 JDK 9 郵件列中說:「這個 JEP 將是平臺上的
一個有用的補充,可是在計劃中,它並不像 Oracle 資助的其餘功能那麼重要,可能會從新考慮 JDK 10 或更高版本中實現。 」
1.2 新的貨幣 API
對許多應用而言貨幣價值都是一個關鍵的特性,但 JDK 對此卻幾乎沒有任何支持。嚴格來說,現有的 java.util.Currency 類只是表明了當前 ISO 4217 貨幣的一個數據結構,但並無關聯的值或者自定義貨幣。JDK 對貨幣的運算及轉換也沒有內建的支持,更別說有一個可以表明貨幣值的標準類型了。
此前,Oracle 公佈的 JSR 354 定義了一套新的 Java 貨幣 API:JavaMoney,計劃會在 Java 9 中正式引入。可是目前沒有出如今 JDK 9中。不過,若是你用的是 Maven 的話,能夠作以下的添加,便可使用相關的 API 處理貨幣:

<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>0.9</version>
</dependency>

代碼參考,能夠訪問 https://github.com/JavaMoney,裏面已經給出了使用說明和示例。

2. 展望

隨着雲計算和AI 等技術浪潮,當前的計算模式和場景正在發生翻天覆地的變化,不只對 Java 的發展速度提出了更高要求,也深入影響着 Java 技術的發展方向。傳統的大型企業或互聯網應用,正在被雲端、容器化應用、模塊化的微服務甚至是函數(FaaS,Function-as-a-Service 所替代。Java雖然標榜面向對象編程,卻絕不顧忌的加入面向接口編程思想,又扯出匿名對象之概念,每增長一個新的東西,對Java的根本所在的面向對象思想的一次衝擊。反觀Python,抓住面向對象的本質,又能在函數編程思想方面遊刃有餘。Java對標C/C++,以拋掉內存管理爲賣點,卻又陷入了JVM優化的噩夢。選擇比努力更重要,選擇Java的人更須要對它有更清晰的認識。 Java 須要在新的計算場景下,改進開發效率。這話說的有點籠統,我談一些本身的體會,Java 代碼雖然進行了一些類型推斷等改進,更易用的集合 API 等,但仍然給開發者留下了過於刻板、形式主義的印象,這是一個長期的改進方向。

相關文章
相關標籤/搜索