最通俗易懂的 Java 10 新特性講解


點贊再看,動力無限。Hello world : ) 微信搜「 程序猿阿朗 」。

本文 Github.com/niumoo/JavaNotes未讀代碼博客 已經收錄,有很多知識點和系列文章。

Java 10 新特性

自從 Java 9 開始,Oracle 調整了 Java 版本的發布策略,不再是之前的 N 年一個大版本,取而代之的是 6 個月一個小版本,三年一個大版本,這樣可以讓 Java 的最新改變迅速上線,而小版本的維護周期縮短到下個版本發布之前,大版本的維護周期則是 3 年之久。而 10 就是這么一個小版本,因為 Java 的后續版本基本都會包含之前新特性,所以還是把 Java 10 帶來的改變單獨寫一寫。

1. JEP 322 - 基於時間的版本號

就像上面說的,Java 調整了發布策略,為了適應這種發布節奏,隨着改變的還有 Java 版本號的記錄方式。

版本號的新模式是:$FEATURE.$INTERIM.$UPDATE.$PATCH

  • $FEATURE :基於發布版本,如 Java 10 的 10 。
  • $INTERIM :問題修復和功能增強時 + 1,默認是 0 。
  • $UPDATE :在進行兼容更新,修復新功能安全問題時 +1。
  • $PATCH :特殊問題修復時 +1。

查看自己的 Java 10 版本。

$ java -version
java version "10.0.1" 2018-04-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)

2. JEP 286 - 局部類型推斷

JEP 286 提案讓 Java 增加了局部類型推斷(Local-Variable Type Inference)功能,這讓 Java 可以像 Js 里的 var 或者其他語言的 auto 一樣可以自動推斷數據類型。這其實只是一個新的語法糖,底層並沒有變化,在編譯時就已經把 var 轉化成具體的數據類型了,但是這樣可以減少代碼的編寫。

你可以像下面這樣使用 var 語法。

var hashMap = new HashMap<String, String>();
hashMap.put("微信","wn8398");
var string = "hello java 10";
var stream = Stream.of(1, 2, 3, 4);
var list = new ArrayList<String>();

如果你反編譯編譯后的這段代碼,你會發現還是熟悉的代碼片段。

HashMap<String, String> hashMap = new HashMap();
hashMap.put("微信", "wn8398");
String string = "hello java 10";
Stream<Integer> stream = Stream.of(1, 2, 3, 4);
ArrayList<String> list = new ArrayList();

var 看似好用,其實也有很多限制,官方介紹了 var 只能用於下面的幾種情況。

  1. 僅限帶有初始化的程序的局部變量。
  2. for 循環或者增強for 循環中。
  3. for循環中的聲明。

下面演示三種使用情況。

public static void testVar() {
    // 情況1,沒有初始化會報錯
    // var list;
    var list = List.of(1, 2, 3, 4);
    // 情況2
    for (var integer : list) {
        System.out.println(integer);
    }
    // 情況3
    for (var i = 0; i < list.size(); i++) {
        System.out.println(list.get(i));
    }
}

盡管對 var 的使用場景增加了很多限制,但在實際使用時你還是要注意,就像下面的代碼,你可能一眼並不能看出 result 的數據類型。

var query = "xxx";
var result = dbUtil.executeQuery(query);

3. JEP 317 - 基於 Java 的 JIT 編譯器(實驗性)

這個功能讓基於 Java 開發的 JIT 編譯器 Graal 結合 Java 10 用在 Linux / x64 平台上,這是一個實驗性的 JIT 編譯器,有人說這也是 Java 10 中最具有未來感的引入。Graal 其實在 Java 9 中就已經引入了,它帶來了 Java 中的 AOT (Ahead Of Time)編譯,還支持多種語言,如 Js、Python、Ruby、R、以及其他基於 JVM (如 Java、Kotlin)的和基於 LLVM (如 C、C++)的語言。

想切換到 Graal 可以使用下面的 jvm 參數。

-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler

這里面有一點我覺得很有意思,看這個圖。

Graal 由 Java 編寫

這就很有意思了,Graal 是 Java 語言編寫的,用 Java 編寫的編譯器,然后用來將 Java 字節碼編譯機器代碼。

Graal 官網:https://www.graalvm.org/

4. JEP 310 - 類數據共享

JVM 啟動時有一步是需要在內存中加載類,而如果有多個 jar,加載第一個 jar 的速度是最慢的。這就延長了程序的啟動時間,為了減少這個時間,Java 10 引入了應用程序類數據共享(CDS)機制,它可以把你想共享的類共享在程序之間,使不同的 Java 進程之間共享這個類來減少這個類占用的空間以及加載速度。

5. JEP 307 - G1 並行全GC

早在 Java 9 時就已經引入了 G1 垃圾收集器,G1 的優點很多。而在 Java 10 中還是做了小小調整,當 G1 的並發收集線程不能快速的完成全 GC 時,就會自動切換到並行收集,這可以減少在最壞情況下的 GC 速度。

6. JEP 314 - Unicode 語言標簽擴展

這個提案讓 JDK 實現了最新的 LDML 規范中指定的更多的擴展。

主要增加了下面幾個擴展方法。

java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of

嘗試一下。

Currency chinaCurrency = Currency.getInstance(Locale.CHINA);
Currency usCurrency = Currency.getInstance(Locale.US);
System.out.println("本地貨幣:" + chinaCurrency);
System.out.println("US.貨幣:" + usCurrency);

String displayName = Locale.getDefault().getDisplayName();
String displayLanguage = Locale.getDefault().getDisplayLanguage();
String displayCountry = Locale.getDefault().getDisplayCountry();
System.out.println("本地名稱:" + displayName);
System.out.println("本地語言:" + displayLanguage);
System.out.println("本地國家:" + displayCountry);
int firstDayOfWeek = Calendar.getInstance().getFirstDayOfWeek();
System.out.println("本地每周第一天:" + firstDayOfWeek);

輸出結果。

本地貨幣:CNY
US.貨幣:USD
本地名稱:中文 (中國)
本地語言:中文
本地國家:中國
本地每周第一天:1

7. API 更新

Java 10 刪除了部分 API,也增加了一些實用方法。比如可以通過 Collection.copyOf 復制得到一個不可改變集合,即使原來的集合元素發生了變化也不會有影響。

var list = new ArrayList<String>();
list.add("wechat");
list.add("wn8398");
List<String> copyList = List.copyOf(list);
list.add("test");
System.out.println(copyList);
// result
// [wechat, wn8398]

也為 Optional 增加了一個新的方法 orElseThrow。調用這個方法也可以獲取到 optional 中的 value , 但是如果 valuenull ,就會拋出異常。

另外在 Stream 最后收集數據的時候,Collectors 可以直接指定收集的集合為不可變集合,像下面這樣。

list.stream().collect(Collectors.toUnmodifiableList());
list.stream().collect(Collectors.toUnmodifiableSet());

其他更新

Java 10 的更新內容不止這些,上面只是列舉了常用的以及比較有意思的新特性。還有部分更新如:

  1. JEP 312:Thread-Local Handshakes,JVM 內部功能,可以提高 JVM 性能。
  2. JEP 313:刪除了 javah 工具,說是刪除,其實功能已經包含在 Java 8 中的 javac 里。
  3. JEP 316:讓 JVM 可以在備用的存儲設備(如 NV-DIMM)上分配堆內存,而不用更改程序代碼。
  4. JEP 319:在JDK中提供一組默認的根證書頒發機構(CA)證書。

文章案例都已經上傳到 Github:niumoo/jdk-feature

<完>

Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。

點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。


文章持續更新,可以關注公眾號「 程序猿阿朗 」或訪問「未讀代碼博客 」。

回復【資料】有我准備的各系列知識點和必看書籍。

本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。

等你好久


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM