點贊再看,動力無限。微信搜「 程式猿阿朗 」,認認真真寫文章。
本文 Github.com/niumoo/JavaNotes 和 未讀程式碼部落格 已經收錄,有很多知識點和系列文章。
Java 15 在 2020 年 9 月釋出,雖然不是長久支援版本,但是也帶來了 14 個新功能,這些新功能中有不少是十分實用的。
Java 15 官方下載:https://jdk.java.net/archive/
Java 15 官方文件:https://openjdk.java.net/projects/jdk/15/
Java 15 新功能:
JEP | 描述 |
---|---|
JEP 339 | 愛德華曲線演算法(EdDSA) |
JEP 360 | Sealed Classes(密封類)預覽 |
JEP 371 | Hidden Classes(隱藏類) |
JEP 372 | 移除 Nashorn JavaScript 引擎 |
JEP 373 | 重新實現 DatagramSocket APII |
JEP 374 | 禁用和廢棄偏向鎖(Biased Locking) |
JEP 375 | instanceof 型別匹配 (二次預覽) |
JEP 377 | ZGC: 可擴充套件低延遲垃圾收集器(正式釋出) |
JEP 378 | 文字塊 |
JEP 379 | Shenandoah: 低停頓時間的垃圾收集器 |
JEP 381 | 刪除 Solaris 和 SPARC 埠 |
JEP 383 | 外部記憶體訪問 API(第二個孵化器)) |
JEP 384 | Records (二次預覽) |
JEP 385 | 廢棄 RMI 啟用機制 |
1. JEP 339 愛德華曲線演算法(EdDSA)
Java 15 中增加了一個新的密碼學演算法,愛德華曲線演算法(EdDSA)簽名演算法。它是由 Schnorr 演算法發展而來,在 RFC8032 中被定義實現。
package com.wdbyte;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.util.Base64;
public class JEP339 {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
KeyPair kp = kpg.generateKeyPair();
byte[] msg = "www.wdbyte.com".getBytes(StandardCharsets.UTF_8);
Signature sig = Signature.getInstance("Ed25519");
sig.initSign(kp.getPrivate());
sig.update(msg);
byte[] s = sig.sign();
System.out.println(Base64.getEncoder().encodeToString(s));
}
}
輸出結果:
VXlpxapU+LSWjVQ0QNJvdpUh6VI6PjSwOQ2pHu65bCfnLR13OyWKunlc9rc+7SMxCh2Mnqf7TmC/iOG8oimbAw==
2. JEP 360:Sealed Classes(密封類)預覽
我們都知道,在 Java 中如果想讓一個類不能被繼承和修改,這時我們應該使用 final
關鍵字對類進行修飾。不過這種要麼可以繼承,要麼不能繼承的機制不夠靈活,有些時候我們可能想讓某個類可以被某些型別繼承,但是又不能隨意繼承,是做不到的。Java 15 嘗試解決這個問題,引入了 sealed
類,被 sealed
修飾的類可以指定子類。這樣這個類就只能被指定的類繼承。
而且 sealed
修飾的類的機制具有傳遞性,它的子類必須使用指定的關鍵字進行修飾,且只能是 final
、sealed
、non-sealed
三者之一。
示例:犬類(Dog)只能被牧羊犬(Collie)和田園犬(TuGou)繼承,使用 sealed
關鍵字。
package com.wdbyte;
public sealed interface Dog permits Collie, TuGou {
//...
}
牧羊犬(Collie)只能被邊境牧羊犬(BorderCollie)繼承。
package com.wdbyte;
/**
* 牧羊犬
* @author www.wdbyte.com
*/
public sealed class Collie implements Dog permits BorderCollie {
}
邊境牧羊犬(BorderCollie)不能被繼承,使用 final
關鍵字。
package com.wdbyte;
/**
*
* @author www.wdbyte.com
*/
public final class BorderCollie extends Collie{
}
田園犬(ToGou)可以被任意繼承,使用 non-sealed
關鍵字。
package com.wdbyte;
/**
* @author niulang
*/
public non-sealed class TuGou implements Dog {
}
3. JEP 371:Hidden Classes(隱藏類)
這個特性讓開發者可以引入一個無法被其他地方發現使用,且類的生命週期有限的類。這對執行時動態生成類的使用方式十分有利,可以減少記憶體佔用,下面是一個使用示例。
package com.wdbyte;
public class JEP371Test {
public static String lookup() {
return "www.wdbyte.com";
}
}
把類 JEP371Test
編譯後的 Class 轉換成 Base64
,然後使用 Java 15 新特性載入呼叫類中的 lookup
方法。
package com.wdbyte;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Base64;
/**
* @author www.wdbyte.com
*/
public class JEP371 {
private static String CLASS_INFO = "yv66vgAAADQAFAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCAAIAQAOd3d3LndkYnl0ZS5jb20HAAoBABVjb20vd2RieXRlL0pFUDM3MVRlc3QBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAEdGhpcwEAF0xjb20vd2RieXRlL0pFUDM3MVRlc3Q7AQAGbG9va3VwAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAPSkVQMzcxVGVzdC5qYXZhACEACQACAAAAAAACAAEABQAGAAEACwAAAC8AAQABAAAABSq3AAGxAAAAAgAMAAAABgABAAAAAwANAAAADAABAAAABQAOAA8AAAAJABAAEQABAAsAAAAbAAEAAAAAAAMSB7AAAAABAAwAAAAGAAEAAAAEAAEAEgAAAAIAEw==";
public static void main(String[] args) throws Throwable {
byte[] classInBytes = Base64.getDecoder().decode(CLASS_INFO);
Class<?> proxy = MethodHandles.lookup()
.defineHiddenClass(classInBytes, true, MethodHandles.Lookup.ClassOption.NESTMATE)
.lookupClass();
System.out.println(proxy.getName());
MethodHandle mh = MethodHandles.lookup().findStatic(proxy, "lookup", MethodType.methodType(String.class));
String result = (String) mh.invokeExact();
System.out.println(result);
}
}
輸出結果:
com.wdbyte.JEP371Test/0x0000000800c01800
www.wdbyte.com
4. JEP 372:移除 Nashorn JavaScript 引擎
Nashorn JavaScript 引擎在 Java 8 中被引入,在 Java 11 中被標記為廢棄。由於 ECMAScript 語言發展很快,維護 Nashorn JavaScript 的成本過於高昂,在 Java 15 中被徹底刪除。
擴充套件閱讀:Nashorn JavaScript Engine,Deprecate the Nashorn JavaScript Engine
5. JEP 373:重新實現 DatagramSocket API
Java 13 中重新實現了舊的 Socket API,在介紹 Java 13 時還有一部分做了這方面的介紹。
現在,Java 15 重新實現了遺留的 DatagramSocket
。
擴充套件閱讀:Java 13 新功能介紹
6. JEP 374:禁用和廢棄偏向鎖(Biased Locking)
在之前,JVM 在處理同步操作,如使用 synchronized
同步時,有一套鎖的升級機制,其中有一個鎖機制就是偏向鎖。然而通過目前的 Java 開發環境來看,使用這些被 synchronized
同步的類的機會並不多,如開發者更喜歡使用 HashMap
或者 ArrayList
而非 HashTable
和 Vector
。
即使換個角度,當初使用偏向鎖是為了提高效能,如今看來效能提升的程度和使用次數都不太有用。而偏向鎖的引入增加了 JVM 的複雜性。
所以現在偏向鎖被預設禁用,在不久的將來將會徹底刪除,對於 Java 15,我們仍然可以使用-XX:+UseBiasedLocking
啟用偏向鎖定,但它會提示 這是一個已棄用的 API。
7. JEP 375:instanceof 型別匹配 (二次預覽)
instanceof
型別匹配在 Java 14 中已經改進,這次僅僅再次預覽,沒有任何改動,用於接受更多的使用反饋。這個特性在 Java 16 中成為正式特性。
在之前,使用 instanceof
進行型別判斷之後,需要進行物件型別轉換後才能使用。
package com.wdbyte;
import java.util.ArrayList;
import java.util.List;
public class Java14BeaforInstanceof {
public static void main(String[] args) {
Object obj = new ArrayList<>();
if (obj instanceof ArrayList) {
ArrayList list = (ArrayList)obj;
list.add("www.wdbyte.com");
}
System.out.println(obj);
}
}
而在 Java 14 中,可以在判斷型別時指定變數名稱進行型別轉換,方便了使用。
package com.wdbyte;
import java.util.ArrayList;
public class Java14Instanceof {
public static void main(String[] args) {
Object obj = new ArrayList<>();
if (obj instanceof ArrayList list) {
list.add("www.wdbyte.com");
}
System.out.println(obj);
}
}
可以看到,在使用 instanceof
判斷型別成立後,會自動強制轉換型別為指定型別。
輸出結果:
[www.wdbyte.com]
擴充套件閱讀:Java 14 新功能介紹
8. JEP 377:ZGC: 可擴充套件低延遲垃圾收集器(正式釋出)
ZGC 垃圾收集器在 Java 11 中被引入,但是因為收集器的複雜性,當初決定逐漸引入。然後不斷的聽取使用者的反饋建議修復問題。而現在,已經很久沒有收到使用者的問題反饋了,ZGC 是時候投入正式使用階段了。所以在 Java 15 中 ZGC 正式釋出,可以使用下面的引數啟用 ZGC。
$ java -XX:+UseZGC className
9. JEP 378: 文字塊
文字塊在 Java 12 JEP 326 原始字串文字 中引入,在 Java 13 JEP 355:文字塊(預覽) 中開始預覽,在 Java 14 JEP 368:文字塊(第二次預覽),而現在,在 Java 15 ,文字塊是正式的功能特性了。
String content = """
{
"upperSummary": null,\
"sensitiveTypeList": null,
"gmtModified": "2011-08-05\s10:50:09",
}
""";
System.out.println(content);
擴充套件閱讀:Java 14 新功能介紹- JEP368 文字塊
10. JEP 379:Shenandoah: 低停頓時間的垃圾收集器
Shenandoah 垃圾收集器在 Java 12 中開始引入,Java 15 中成為了正式功能的一部分,可以使用下面的引數啟用 Shenandoah 垃圾收集器。
java -XX:+UseShenandoahGC
但是 openJDK 15 中預設是沒有 Shenandoah 收集器,想要使用此功能可以下載 AdoptOpenJDK。
為什麼 openJDK 中沒有 Shenandoah 垃圾收集器?
Shenandoah 是一個高效能、低暫停時間的垃圾收集器,它是 Red Hat 主導的專案。當 Red Hat 第一次提議將 Shenandoah 貢獻給 OpenJDK 時,Oracle 明確表示不想支援它,OpenJDK 作為一個免費軟體,不想支援 Red Hat 的 Shenandoah 完全沒有問題。
最後 Red Hat 選擇和 Oracle 合作設計一個真正乾淨的可插拔垃圾收集器介面,允許任何人輕鬆選擇垃圾收集器以包含在他們的構建中。最終 Shenandoah 進入了 JDK 12,但是沒有構建進 OpenJDK。
11. JEP 384:Records(二次預覽)
在 Java 14 中引入了 Record 類,Java 15 中對 Record 進行了增強。使它可以支援密封型別、Record 註解以及相關的反射 API 等。
示例:Record 支援密封(sealed)型別。
package com.wdbyte;
/**
* @author www.wdbyte.com
*/
public sealed interface DataBase permits DataBaseSelect, DataBaseUpdate {
}
final record DataBaseSelect(@Deprecated String table, String sql) implements DataBase {
}
final record DataBaseUpdate() implements DataBase {
}
在 java.lang.Class
增加了兩個公共方法用於獲取 Record 類資訊:
-
RecordComponent[] getRecordComponents()
-
boolean isRecord()
其他更新
JEP 381:刪除 Solaris 和 SPARC 埠
Java 14 JEP 362棄用了 Solaris/SPARC、Solaris/x64 和 Linux/SPARC 埠,現在它在 Java 15 中被正式刪除。
JEP 383:外部記憶體訪問 API(第二個孵化器)
JEP 385:廢棄 RMI 啟用機制
只是廢棄 RMI 啟用機制,不影響 RMI 其他功能。
參考
- https://openjdk.java.net/projects/jdk/15/
- https://docs.oracle.com/en/java/javase/14/docs/specs/rmi/activation.html
- https://mkyong.com/java/what-is-new-in-java-15/
訂閱
Hello world : ) 我是阿朗,一線技術工具人,認認真真寫文章。
點贊的個個都是人才,不僅長得帥氣好看,說話還好聽。
文章持續更新,可以關注公眾號「 程式猿阿朗 」或訪問「未讀程式碼部落格 」。
回覆【資料】有我準備的各系列知識點和必看書籍。
本文 Github.com/niumoo/JavaNotes 已經收錄,有很多知識點和系列文章,歡迎Star。