點贊再看,動力無限。Hello world : ) 微信搜「 程序猿阿朗 」。
本文 Github.com/niumoo/JavaNotes 和 未讀代碼博客 已經收錄,有很多知識點和系列文章。
自從 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
只能用於下面的幾種情況。
- 僅限帶有初始化的程序的局部變量。
for
循環或者增強for
循環中。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 語言編寫的,用 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
, 但是如果 value
為 null
,就會拋出異常。
另外在 Stream
最后收集數據的時候,Collectors
可以直接指定收集的集合為不可變集合,像下面這樣。
list.stream().collect(Collectors.toUnmodifiableList());
list.stream().collect(Collectors.toUnmodifiableSet());
其他更新
Java 10
的更新內容不止這些,上面只是列舉了常用的以及比較有意思的新特性。還有部分更新如:
- JEP 312:Thread-Local Handshakes,JVM 內部功能,可以提高 JVM 性能。
- JEP 313:刪除了
javah
工具,說是刪除,其實功能已經包含在Java 8
中的javac
里。 - JEP 316:讓 JVM 可以在備用的存儲設備(如 NV-DIMM)上分配堆內存,而不用更改程序代碼。
- JEP 319:在JDK中提供一組默認的根證書頒發機構(CA)證書。
文章案例都已經上傳到 Github:niumoo/jdk-feature
<完>
Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。
點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。
文章持續更新,可以關注公眾號「 程序猿阿朗 」或訪問「未讀代碼博客 」。
回復【資料】有我准備的各系列知識點和必看書籍。
本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。