Java9的新特性的總結

Panda_XiaoXi發表於2017-11-28

Java9的新特性總結

102: Process API Updates
110: HTTP 2 Client
143: Improve Contended Locking
158: Unified JVM Logging
165: Compiler Control
193: Variable Handles
197: Segmented Code Cache
199: Smart Java Compilation, Phase Two
200: The Modular JDK
201: Modular Source Code
211: Elide Deprecation Warnings on Import Statements
212: Resolve Lint and Doclint Warnings
213: Milling Project Coin
214: Remove GC Combinations Deprecated in JDK 8
215: Tiered Attribution for javac
216: Process Import Statements Correctly
217: Annotations Pipeline 2.0
219: Datagram Transport Layer Security (DTLS)
220: Modular Run-Time Images
221: Simplified Doclet API
222: jshell: The Java Shell (Read-Eval-Print Loop)
223: New Version-String Scheme
224: HTML5 Javadoc
225: Javadoc Search
226: UTF-8 Property Files
227: Unicode 7.0
228: Add More Diagnostic Commands
229: Create PKCS12 Keystores by Default
231: Remove Launch-Time JRE Version Selection
232: Improve Secure Application Performance
233: Generate Run-Time Compiler Tests Automatically
235: Test Class-File Attributes Generated by javac
236: Parser API for Nashorn
237: Linux/AArch64 Port
238: Multi-Release JAR Files
240: Remove the JVM TI hprof Agent
241: Remove the jhat Tool
243: Java-Level JVM Compiler Interface
244: TLS Application-Layer Protocol Negotiation Extension
245: Validate JVM Command-Line Flag Arguments
246: Leverage CPU Instructions for GHASH and RSA
247: Compile for Older Platform Versions
248: Make G1 the Default Garbage Collector
249: OCSP Stapling for TLS
250: Store Interned Strings in CDS Archives
251: Multi-Resolution Images
252: Use CLDR Locale Data by Default
253: Prepare JavaFX UI Controls & CSS APIs for Modularization
254: Compact Strings
255: Merge Selected Xerces 2.11.0 Updates into JAXP
256: BeanInfo Annotations
257: Update JavaFX/Media to Newer Version of GStreamer
258: HarfBuzz Font-Layout Engine
259: Stack-Walking API
260: Encapsulate Most Internal APIs
261: Module System
262: TIFF Image I/O
263: HiDPI Graphics on Windows and Linux
264: Platform Logging API and Service
265: Marlin Graphics Renderer
266: More Concurrency Updates
267: Unicode 8.0
268: XML Catalogs
269: Convenience Factory Methods for Collections
270: Reserved Stack Areas for Critical Sections
271: Unified GC Logging
272: Platform-Specific Desktop Features
273: DRBG-Based SecureRandom Implementations
274: Enhanced Method Handles
275: Modular Java Application Packaging
276: Dynamic Linking of Language-Defined Object Models
277: Enhanced Deprecation
278: Additional Tests for Humongous Objects in G1
279: Improve Test-Failure Troubleshooting
280: Indify String Concatenation
281: HotSpot C++ Unit-Test Framework
282: jlink: The Java Linker
283: Enable GTK 3 on Linux
284: New HotSpot Build System
285: Spin-Wait Hints
287: SHA-3 Hash Algorithms
288: Disable SHA-1 Certificates
289: Deprecate the Applet API
290: Filter Incoming Serialization Data
291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector
292: Implement Selected ECMAScript 6 Features in Nashorn
294: Linux/s390x Port
295: Ahead-of-Time Compilation
297: Unified arm32/arm64 Port
298: Remove Demos and Samples
299: Reorganize Documentation複製程式碼

java9的新特性
java9的新特性

  • 模組化系統

模組化是一個很通用的概念。在軟體中,模組化可以運用到編寫和實現一個程式和計算系統,他們都是作為獨立的模組,而不是作為一個單一的和完整的設計。

Java 9中主要的變化是已經實現的模組化系統。模組化的引入使得JDK可以在更小的裝置中使用。採用模組化系統的應用程式只需要這些應用程式所需的那部分JDK模組,而非是整個JDK框架了。模組化系統也可以將公共的類封裝到一個模組中。因此一個封裝在模組中的定義為public的類不能再任何地方使用,除非一個模組顯式的定義了這個模組。由於Java 9的這個變化,Java內部的API(例如com.sun.*)預設情況下是不能使用的。

所有的模組將需要在module-ionfo.java檔案中進行描述,該檔案位於Java程式碼結構的頂層。

module me.aboullaite.java9.modules.car {
    requires me.aboullaite.java9.modules.engines;//依賴的模組
    exports me.aboullaite.java9.modules.car.handling;//在模組中匯出的包
}複製程式碼

我們的模組car(汽車)需要依賴+模組engine(引擎)和需要匯出handling(操作)包。

更多例子可以檢視OpenJDK中專案Jigsaw:模組化系統快速入門

  • JShell–Java 9 REPL

REPL是一種快速執行語句的命令列工具。

在Java中,如果你想執行一個簡單的語句,我們要麼建立一個帶main方法的類,要麼建立一個可以執行的Test類。當你正在啟動Java程式的時候,如果你想執行某些語句並且想立刻看見執行結果,上面的做法看起來不是那麼有用了。(更像python執行程式命令列的模式...)

JShell試圖去解決這個問題。Java開發者可以利用JShell在沒有建立類的情況下直接宣告變數,計算表示式,執行語句。JShell也可以從檔案中載入語句或者將語句儲存到檔案中。並且JShell也可以是tab鍵進行自動補全的特性。

  • 集合工廠方法

在Java 9之前,Java只能利用一些實用方法(例如:Collections.unmodifiableCollection(Collection<? extends T> c))建立一個不可修改檢視的集合。例如,我們可以在Java 8中使用一條如下所示的語句,建立一個Collection的不可修改的檢視。雖然這是最簡單的建立方式,但是看起來很糟糕!不是嗎?

 Map<String,String> immutableMap = 
      Collections.unmodifiableMap(
         new HashMap<String,String>(){
           {
           put("key1","value1");
           put("key2","value2");
           put("key3","value3");
           }
         });複製程式碼

在Java9中引入了一些有用的工廠方法來建立不可修改的集合:

Map<String,String> immutableMap = Map.of("key1","value1","key2","value2","key3","value3");複製程式碼

工廠方法的例子如下:

//不可修改的空集合
List<String> emptyImmutableList = List.of();
Set<String> emptyImmutableSet = Set.of();
Map emptyImmutableMap = Map.of();

//不可修改的集合
List<String> immutableList = List.of("one","two");
Set<String> immutableSet = Set.of("value1","value2");
Map<String,String> immutableMap = Map.of("key1","value1","key2","value2","key3","value3");複製程式碼
  • 介面中的私有方法

Java 8的介面引入了預設方法和靜態方法。雖然Java 8首次計劃實現介面的私有方法,在Java 9中實現。預設方法和靜態方法可以共享介面中的私有方法,因此避免了程式碼冗餘,這也使程式碼更加清晰。如果私有方法是靜態的,那這個方法就屬於這個介面的。並且沒有靜態的私有方法只能被在介面中的例項呼叫。

interface InterfaceWithPrivateMethods{
    private static String staticPrivate(){
        return "static private";
    }

    private String instancePrivate(){
        return "instance private";
    }

    default void check(){
        String result = staticPrivate();

        InterfaceWithPrivateMethods p = new InterfaceWithPrivateMethods(){
            //匿名類    
        };

        result = p.instancePrivate();
    }

}複製程式碼
  • 響應式流

JDK9中的Flow API對應響應式流規範,響應式流規範是一種事實標準。JEP 266包含了一組最小介面集合,這組介面能捕獲核心的非同步釋出與訂閱。

java.util.concurrent.Flow包含以下4個介面:

Flow.Processor(處理器)

Flow.Publisher(釋出者)

Flow.Subscriber(訂閱者)

Flow.Subscription(訂閱管理器)

這些介面都支援響應式流釋出-訂閱框架。Java 9也提供了實用類SubmissionPublisher。一個釋出者產生一個或多個物品,這些物品由一個或多個消費者消耗。並且訂閱者由訂閱管理器管理。訂閱管理器連線釋出者和訂閱者。

  • 多解析度影象API–JEP 251

目標是定義多解析度影象API,這樣開發者就能很容易的操作和展示不同解析度的影象了。這個新的API定義在java.awt.image包中,這個API能給我們帶來如下的幫助:

  1. 將不同解析度的影象封裝到一張(多解析度的)影象中,作為它的變體。

  2. 獲取這個影象的所有變體。

  3. 獲取特定解析度的影象變體–表示一張已知解析度單位為DPI的特定尺寸大小的邏輯影象,並且這張影象是最佳的變體。

基於當前螢幕解析度大小和運用的影象轉換演算法,java.awt.Graphics類可以從介面MultiResolutionImage獲取所需的變體。
java.awt.image.AbstractMultiResolutionImage類提供了java.awt.image.AbstractMultiResolutionImage 預設實現。
AbstractMultiResolutionImage的基礎實現是java.awt.image.BaseMultiResolutionImage。

  • 程式API的改進

加入了用來控制和管理作業系統的程式的API,在Java9中,期望程式碼能獲取LINUX PID

在以前的版本中的方法:

public static void main(String[] args) throws Exception{
    Process proc = Runtime.getRuntime().exec(new String[]{"/bin/sh","-c","echo $PPID"});

    if(proc.waitFor() == 0){
        InputStream in = proc.getInputStream();
        int available = in.available();
        byte[] outputBytes = new byte[available];

        in.read(outputBytes);
        String pid = new String(outputBytes);

        System.out.println("你的PID是:"+pid);
    }

}複製程式碼

在java9中變換為如下的方式(同樣支援所有的作業系統):

System.out.println("你的PID是:" + Process.getCurrentPid());複製程式碼
  • 異常的處理

在Java 7中,try-with-resouces語法要求為每一個資源宣告一個新的變數,而且這些資源由try-with-resources語句進行管理。

在Java 9中:如果一個資源被final或者等效於final變數引用,則在不需要宣告一個新的變數的情況下,try-with-resources就可以管理這個資源。

MyAutoCloseable mac = new MyAutoCloseable();
try(mac){
//do some stuff with mac
}

try(new MyAutoCloseable(){}.finalWrapper.finalCloseable){
//do some stuff with finalCloseable
}

  • diamond操作符範圍的延伸

Java 7給出的鑽石操作符使我們編寫程式碼更簡單了。在下面的例子中,你可以看見Java 7中List的可讀性更強了,但是Java 7中鑽石操作符不允許在匿名類上使用,但在Java 9中改善了這一情況,允許鑽石操作符在匿名類上使用。下面的例子只有在Java 9中才能通過編譯。

List<String> list = new ArrayList<>(){};複製程式碼
  • 增強的註釋Deprecated

註釋@Deprecated可以標記Java API。註釋@Deprecated有很多種含義,例如它可以表示在不遠的將來的某個時間,被標記的API將會被移除。它也可以表示這個API已經被破壞了,並不應該再被使用。它還有其它很多含義。為了提供更多有關@Deprecated的資訊,@Deprecated新增了forRemoval元素和since元素。

Java SE 9 中也提供了掃描jar檔案的工具jdeprscan。這款工具也可以掃描一個聚合類,這個類使用了Java SE中的已廢棄的API元素。 這個工具將會對使用已經編譯好的庫的應用程式有幫助,這樣使用者就不知道這個已經編譯好的庫中使用了那些已廢棄的API。

  • 統一的JVM日誌

我們很難知道導致JVM效能問題和導致JVM崩潰的根本原因。解決這個問題的一個方法是對所有的JVM元件引入一個單一的系統,這些JVM元件支援細粒度的和易配置的JVM日誌。目前,不同的JVM元件對於日誌使用的是不同的機制和規則,這使得JVM難以進行除錯。

  • 註釋@SafeVarargs範圍的延伸

直到Java 8,@SafeVarargs才能在靜態方法、final方法和構造器上使用。但是這些方法或者構造器是不能被覆蓋的。這些方法中缺少另一個不能被覆蓋的方法,這個方法就是私有方法。Java 9可以將@SafeVarargs新增到私有方法上。下面的例子在Java 9中是正確的,但是在Java 8中就會丟擲編譯時錯誤: 註釋@SafeVarargs不能在非final的例項方法iAmSafeVaragrsMethod上使用。

@SafeVarargs
private void iAmSafeVaragrsMethod(String... varagrgs){
    for(String each : varagrgs){
        System.out.println(each);
    }
}複製程式碼
  • HTTP 2 客戶端

Java 9採用了全新的HTTP客戶端API,這些API支援HTTP/2協議和WebSocket協議,並且替換了遺留的HTTPURLConnectionAPI。這些改變並不應該在Java 9中完成。這些API可以從Incubator(孵化器)模組中獲取。因此在預設情況下,這個模組是不能根據classpath獲取的,需要使用--add-modules命令選項配置這個模組,將這個模組新增到classpath中。

建立一個HTTP Request請求和獲取非同步的響應:

URI testPageURI = new URI("http://127.0.0.1:8080/testPage");
CompletableFuture<HttpResponse> nonBlockingResponse = HttpRequest
        .create(testPageURI)
        .GET().responseAsync();

int tries = 0;
while(!nonBlockingResponse.isDone() && tries++ < 5){
    Thread.sleep(5);
}
if(nonBlockingResponse.isDone()){
    HttpResponse response = nonBlockingResponse.get();
    System.out.println("satus code :"+response.statusCode()+"-->"+response.body(HttpResponse.asString()));
}else{
    nonBlockingResponse.cancel(true);
    System.out.println("cancelling,could not get response");
}複製程式碼
  • HTML5風格的Java幫助文件

Java 8以及之前的版本生成的Java幫助文件是在HTML 4中,而HTML 4已經是很久的標準了。在Java 9中,javadoc命令列中選項部分新增了輸出選項,這個選項的值要麼是HTML 4,要麼是HTML 5。現在HTML 4是預設的輸出標記語言,但是在之後釋出的JDK中,HTML 5將會是預設的輸出標記語言。Java幫助文件還是由三個框架組成的結構構成,這是不會變的,並且以HTML 5輸出的Java幫助文件也保持相同的結構。

  • 其他的特性
1. 保留下劃線字元。變數不能被命名為_;

2. 廢棄Applet API;

3. javac不再支援Java1.4以及之前的版本;

4. 廢棄Java瀏覽器外掛;

5. 棧遍歷API–棧遍歷API能過濾和遲訪問在堆疊跟蹤中的資訊。複製程式碼

更多JDK9的官方文件

相關文章