--- title: Java 14 & 15 æ°ç¹æ§æ¦è§ category: Java tag: - Javaæ°ç¹æ§ --- ## Java14 ### 空æéå¼å¸¸ç²¾åæç¤º éè¿ JVM 忰䏿·»å `-XX:+ShowCodeDetailsInExceptionMessages`ï¼å¯ä»¥å¨ç©ºæéå¼å¸¸ä¸è·åæ´ä¸ºè¯¦ç»çè°ç¨ä¿¡æ¯ï¼æ´å¿«çå®ä½åè§£å³é®é¢ã ```java a.b.c.i = 99; // åè®¾è¿æ®µä»£ç ä¼åç空æé ``` Java 14 ä¹åï¼ ```java Exception in thread "main" java.lang.NullPointerException at NullPointerExample.main(NullPointerExample.java:5) ``` Java 14 ä¹åï¼ ```java // å¢å åæ°åæç¤ºçå¼å¸¸ä¸å¾æç¡®çåç¥äºåªéä¸ºç©ºå¯¼è´ Exception in thread "main" java.lang.NullPointerException: Cannot read field 'c' because 'a.b' is null. at Prog.main(Prog.java:5) ``` ### switch çå¢å¼º(转æ£) Java12 å¼å ¥ç switchï¼é¢è§ç¹æ§ï¼å¨ Java14 å为æ£å¼çæ¬ï¼ä¸éè¦å¢å åæ°æ¥å¯ç¨ï¼ç´æ¥å¨ JDK14 ä¸å°±è½ä½¿ç¨ã Java12 为 switch 表达å¼å¼å ¥äºç±»ä¼¼ lambda è¯æ³æ¡ä»¶å¹é æååçæ§è¡åï¼ä¸éè¦å¤å break ï¼Java13 æä¾äº `yield` æ¥å¨ block ä¸è¿åå¼ã ```java String result = switch (day) { case "M", "W", "F" -> "MWF"; case "T", "TH", "S" -> "TTS"; default -> { if(day.isEmpty()) yield "Please insert a valid day."; else yield "Looks like a Sunday."; } }; System.out.println(result); ``` ### é¢è§æ°ç¹æ§ #### record å ³é®å `record` å ³é®åå¯ä»¥ç®å **æ°æ®ç±»**ï¼ä¸ä¸ª Java ç±»ä¸æ¦å®ä¾åå°±ä¸è½åä¿®æ¹ï¼çå®ä¹æ¹å¼ï¼ä½¿ç¨ `record` ä»£æ¿ `class` å®ä¹çç±»ï¼åªéè¦å£°æå±æ§ï¼å°±å¯ä»¥å¨è·å¾å±æ§çè®¿é®æ¹æ³ï¼ä»¥å `toString()`ï¼`hashCode()`, `equals()`æ¹æ³ 类似äºä½¿ç¨ `class` å®ä¹ç±»ï¼åæ¶ä½¿ç¨äº lombok æä»¶ï¼å¹¶æä¸äº`@Getter,@ToString,@EqualsAndHashCode`注解 ```java /** * è¿ä¸ªç±»å ·æä¸¤ä¸ªç¹å¾ * 1. æææå屿§é½æ¯final * 2. å ¨é¨æ¹æ³ç±æé æ¹æ³ï¼å两个æå屿§è®¿é®å¨ç»æï¼å ±ä¸ä¸ªï¼ * é£ä¹è¿ç§ç±»å°±å¾éå使ç¨recordæ¥å£°æ */ final class Rectangle implements Shape { final double length; final double width; public Rectangle(double length, double width) { this.length = length; this.width = width; } double length() { return length; } double width() { return width; } } /** * 1. 使ç¨record声æçç±»ä¼èªå¨æ¥æä¸é¢ç±»ä¸çä¸ä¸ªæ¹æ³ * 2. å¨è¿åºç¡ä¸è¿éèµ äºequals()ï¼hashCode()æ¹æ³ä»¥åtoString()æ¹æ³ * 3. toStringæ¹æ³ä¸å æ¬æææå屿§çå符串表示形å¼åå ¶åç§° */ record Rectangle(float length, float width) { } ``` #### ææ¬å Java14 ä¸ï¼ææ¬åä¾ç¶æ¯é¢è§ç¹æ§ï¼ä¸è¿ï¼å ¶å¼å ¥äºä¸¤ä¸ªæ°ç转ä¹åç¬¦ï¼ - `\` : 表示è¡å°¾ï¼ä¸å¼å ¥æ¢è¡ç¬¦ - `\s`ï¼è¡¨ç¤ºåä¸ªç©ºæ ¼ ```java String str = "å¡å¿æåï¼ç´ å±¥æå¾ï¼çå¦éæ ï¼ä¸è以èªã"; String str2 = """ å¡å¿æåï¼ç´ å±¥æå¾ï¼ \ çå¦éæ ï¼ä¸è以èªã"""; System.out.println(str2);// å¡å¿æåï¼ç´ å±¥æå¾ï¼ çå¦éæ ï¼ä¸è以èªã String text = """ java c++\sphp """; System.out.println(text); //è¾åºï¼ java c++ php ``` #### instanceof å¢å¼º ä¾ç¶æ¯**é¢è§ç¹æ§** ï¼[Java 12 æ°ç¹æ§](./java12-13.md)ä¸ä»ç»è¿ã ### å ¶ä» - ä» Java11 å¼å ¥ç ZGC ä½ä¸ºç»§ G1 è¿åçä¸ä¸ä»£ GC ç®æ³ï¼ä»æ¯æ Linux å¹³å°å° Java14 å¼å§æ¯æ MacOS å Windowï¼ä¸ªäººæè§æ¯ç»äºå¯ä»¥å¨æ¥å¸¸å¼åå·¥å ·ä¸å ä½éªä¸ ZGC çææäºï¼è½ç¶å ¶å® G1 ä¹å¤ç¨ï¼ - ç§»é¤äº CMS(Concurrent Mark Sweep) å徿¶éå¨ï¼åæèéï¼ - æ°å¢äº jpackage å·¥å ·ï¼æ é å°åºç¨ææ jar å å¤ï¼è¿æ¯æä¸åå¹³å°çç¹æ§å ï¼æ¯å¦ linux ä¸ç`deb`å`rpm`ï¼window å¹³å°ä¸ç`msi`å`exe` ## Java15 ### CharSequence `CharSequence` æ¥å£æ·»å äºä¸ä¸ªé»è®¤æ¹æ³ `isEmpty()` æ¥å¤æå符åºå为空ï¼å¦ææ¯åè¿å trueã ```java public interface CharSequence { default boolean isEmpty() { return this.length() == 0; } } ``` ### TreeMap `TreeMap` æ°å¼å ¥äºä¸é¢è¿äºæ¹æ³ï¼ - `putIfAbsent()` - `computeIfAbsent()` - `computeIfPresent()` - `compute()` - `merge()` ### ZGC(转æ£) Java11 çæ¶å ï¼ZGC è¿å¨è¯éªé¶æ®µã 彿¶ï¼ZGC çåºç°è®©ä¼å¤ Java å¼åè çå°äºåå¾åæ¶å¨çå¦å¤ä¸ç§å¯è½ï¼å æ¤å¤åå ³æ³¨ã ç»è¿å¤ä¸ªçæ¬çè¿ä»£ï¼ä¸æçå®ååä¿®å¤é®é¢ï¼ZGC å¨ Java 15 å·²ç»å¯ä»¥æ£å¼ä½¿ç¨äºï¼ ä¸è¿ï¼é»è®¤çåå¾åæ¶å¨ä¾ç¶æ¯ G1ãä½ å¯ä»¥éè¿ä¸é¢çåæ°å¯å¨ ZGCï¼ ```bash $ java -XX:+UseZGC className ``` ### EdDSA(æ°åç¾åç®æ³) æ°å å ¥äºä¸ä¸ªå®å ¨æ§åæ§è½é½æ´å¼ºçåºäº Edwards-Curve Digital Signature Algorithm ï¼EdDSAï¼å®ç°çæ°åç¾åç®æ³ã è½ç¶å ¶æ§è½ä¼äºç°æç ECDSA å®ç°ï¼ä¸è¿ï¼å®å¹¶ä¸ä¼å®å ¨å代 JDK ä¸ç°æçæ¤åæ²çº¿æ°åç¾åç®æ³( ECDSA)ã ```java KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519"); KeyPair kp = kpg.generateKeyPair(); byte[] msg = "test_string".getBytes(StandardCharsets.UTF_8); Signature sig = Signature.getInstance("Ed25519"); sig.initSign(kp.getPrivate()); sig.update(msg); byte[] s = sig.sign(); String encodedString = Base64.getEncoder().encodeToString(s); System.out.println(encodedString); ``` è¾åºï¼ ``` 0Hc0lxxASZNvS52WsvnncJOH/mlFhnA8Tc6D/k5DtAX5BSsNVjtPF4R4+yMWXVjrvB2mxVXmChIbki6goFBgAg== ``` ### ææ¬å(转æ£) å¨ Java 15 ï¼ææ¬åæ¯æ£å¼çåè½ç¹æ§äºã ### éèç±»(Hidden Classes) éèç±»æ¯ä¸ºæ¡æ¶ï¼frameworksï¼æè®¾è®¡çï¼éèç±»ä¸è½ç´æ¥è¢«å ¶ä»ç±»çåèç 使ç¨ï¼åªè½å¨è¿è¡æ¶çæç±»å¹¶éè¿åå°é´æ¥ä½¿ç¨å®ä»¬ã ### é¢è§æ°ç¹æ§ #### å¯å°ç±» **å¯å°ç±»ï¼Sealed Classesï¼** æ¯ Java 15 ä¸çä¸ä¸ªé¢è§æ°ç¹æ§ã 没æå¯å°ç±»ä¹åï¼å¨ Java ä¸å¦ææ³è®©ä¸ä¸ªç±»ä¸è½è¢«ç»§æ¿åä¿®æ¹ï¼æä»¬å¯ä»¥ä½¿ç¨`final` å ³é®å对类è¿è¡ä¿®é¥°ãä¸è¿ï¼è¿ç§æ¹å¼ä¸å¤ªçµæ´»ï¼ç´æ¥æä¸ä¸ªç±»çç»§æ¿åä¿®æ¹æ¸ éç»å µæ»äºã å¯å°ç±»å¯ä»¥å¯¹ç»§æ¿æè å®ç°å®ä»¬çç±»è¿è¡éå¶ï¼è¿æ ·è¿ä¸ªç±»å°±åªè½è¢«æå®ç类继æ¿ã ```java // æ½è±¡ç±» Person åªå 许 Employee å Manager ç»§æ¿ã public abstract sealed class Person permits Employee, Manager { //... } ``` å¦å¤ï¼ä»»ä½æ©å±å¯å°ç±»çç±»æ¬èº«é½å¿ 须声æä¸º `sealed`ã`non-sealed` æ `final`ã ```java public final class Employee extends Person { } public non-sealed class Manager extends Person { } ```  妿å 许æ©å±çåç±»åå°éç±»å¨åä¸ä¸ªæºä»£ç æä»¶éï¼å°éç±»å¯ä»¥ä¸ä½¿ç¨ permits è¯å¥ï¼Java ç¼è¯å¨å°æ£ç´¢æºæä»¶ï¼å¨ç¼è¯æä¸ºå°é类添å ä¸è®¸å¯çåç±»ã #### instanceof 模å¼å¹é Java 15 并没æå¯¹æ¤ç¹æ§è¿è¡è°æ´ï¼ç»§ç»é¢è§ç¹æ§ï¼ä¸»è¦ç¨äºæ¥åæ´å¤ç使ç¨åé¦ã 卿ªæ¥ç Java çæ¬ä¸ï¼Java çç®æ æ¯ç»§ç»å®å `instanceof` 模å¼å¹é æ°ç¹æ§ã ### å ¶ä» - **Nashorn JavaScript 弿彻åºç§»é¤**ï¼Nashorn ä» Java8 å¼å§å¼å ¥ç JavaScript 弿ï¼Java9 对 Nashorn åäºäºå¢å¼ºï¼å®ç°äºä¸äº ES6 çæ°ç¹æ§ãå¨ Java 11 ä¸å°±å·²ç»è¢«å¼ç¨ï¼å°äº Java 15 就彻åºè¢«å é¤äºã - **DatagramSocket API éæ** - **ç¦ç¨ååºå¼ååéï¼Biased Lockingï¼**ï¼ååéçå¼å ¥å¢å äº JVM ç夿æ§å¤§äºå ¶å¸¦æ¥çæ§è½æåãä¸è¿ï¼ä½ ä»ç¶å¯ä»¥ä½¿ç¨ `-XX:+UseBiasedLocking` å¯ç¨ååéå®ï¼ä½å®ä¼æç¤º è¿æ¯ä¸ä¸ªå·²å¼ç¨ç APIã - ......