Java语言个性系列
  • Java5的新个性
  • Java6的新个性
  • Java7的新个性
  • Java8的新个性
  • Java9的新个性
  • Java10的新个性
  • Java11的新个性
  • Java12的新个性
  • Java13的新个性
  • Java14的新个性
  • Java15的新个性
  • Java16的新个性
  • Java17的新个性
  • Java18的新个性
  • Java19的新个性
  • Java20的新个性
  • Java21的新个性
  • Java22的新个性

本文次要讲述一下Java21的新个性

版本号

java -versionopenjdk version "21" 2023-09-19OpenJDK Runtime Environment (build 21+35-2513)OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)
从version信息能够看出是build 21+35

个性列表

JEP 430: String Templates (Preview)

在java21之前,字符串拼接或者字符串与表达式组合次要是用StringBuilder、String::format、java.text.MessageFormat,不过可读性都不是太好,java21引入了StringTemplate(java.lang.StringTemplate)来解决这个问题。

@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)public interface StringTemplate {    List<String> fragments();    List<Object> values();    default String interpolate() {        return StringTemplate.interpolate(fragments(), values());    }    default <R, E extends Throwable> R    process(Processor<? extends R, ? extends E> processor) throws E {        Objects.requireNonNull(processor, "processor should not be null");        return processor.process(this);    }    static String interpolate(List<String> fragments, List<?> values) {        Objects.requireNonNull(fragments, "fragments must not be null");        Objects.requireNonNull(values, "values must not be null");        int fragmentsSize = fragments.size();        int valuesSize = values.size();        if (fragmentsSize != valuesSize + 1) {            throw new IllegalArgumentException("fragments must have one more element than values");        }        JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();        return JTA.interpolate(fragments, values);    }    Processor<String, RuntimeException> STR = StringTemplate::interpolate;    Processor<StringTemplate, RuntimeException> RAW = st -> st;    @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)    @FunctionalInterface    public interface Processor<R, E extends Throwable> {        R process(StringTemplate stringTemplate) throws E;        static <T> Processor<T, RuntimeException> of(Function<? super StringTemplate, ? extends T> process) {            return process::apply;        }        @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)        public sealed interface Linkage permits FormatProcessor {            MethodHandle linkage(List<String> fragments, MethodType type);        }    }}

StringTemplate是个接口,它定义了fragments、values、interpolate、process办法,同时提供了interpolate、process办法的默认实现;同时内置了两个processor,别离是STR和RAW,他们的区别在于RAW能够获取到StringTemplate类型,STR则是StringTemplate执行了interpolate办法之后的后果,取得到的是最终后果String;其根本语法就是用\{}来蕴含变量或者表达式

RAW示例

    @Test    public void testRaw() {        int x = 10;        int y = 20;        StringTemplate st = RAW."\{x} + \{y} = \{x + y}";        List<String> fragments = st.fragments();        List<Object> values = st.values();        log.info("fragments:{}, values:{}, st:{}", fragments, values, st.interpolate());    }
输入fragments:[, + , = , ], values:[10, 20, 30], st:10 + 20 = 30
STR示例
    @Test    public void testStr() {        String name = "Joan";        String info = STR."My name is \{name}";        System.out.println(info);    }

输入My name is Joan

也反对办法调用和表达式

    @Test    public void testStrExpression() {        String filePath = "tmp.dat";        File file = new File(filePath);        String msg = STR. "The file \{ filePath } \{ file.exists() ? "does" : "does not" } exist" ;        System.out.println(msg);    }
最初输入The file tmp.dat does not exist

对于还有格式化需要的,提供了java.util.FMT

    @Test    public void testFmt() {        record Rectangle(String name, double width, double height) {            double area() {                return width * height;            }        }        Rectangle[] zone = new Rectangle[] {                new Rectangle("Alfa", 17.8, 31.4),                new Rectangle("Bravo", 9.6, 12.4),                new Rectangle("Charlie", 7.1, 11.23),        };        String table = FMT."""    Description     Width    Height     Area    %-12s\{zone[0].name}  %7.2f\{zone[0].width}  %7.2f\{zone[0].height}     %7.2f\{zone[0].area()}    %-12s\{zone[1].name}  %7.2f\{zone[1].width}  %7.2f\{zone[1].height}     %7.2f\{zone[1].area()}    %-12s\{zone[2].name}  %7.2f\{zone[2].width}  %7.2f\{zone[2].height}     %7.2f\{zone[2].area()}    \{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()}    """;        System.out.println(table);    }

也能够自定义processor

@Test    public void testCustomProcessor() {        var MYJSON = StringTemplate.Processor.of(                (StringTemplate st) -> com.alibaba.fastjson.JSON.parseObject(st.interpolate())        );        String name    = "Joan Smith";        String phone   = "555-123-4567";        String address = "1 Maple Drive, Anytown";        JSONObject doc = MYJSON."""    {        "name":    "\{name}",        "phone":   "\{phone}",        "address": "\{address}"    }    """;        System.out.println(doc);    }

JEP 431: Sequenced Collections

java21引入了java.util.SequencedCollection、java.util.SequencedMap来对立各类汇合的程序办法办法

public interface SequencedCollection<E> extends Collection<E> {    SequencedCollection<E> reversed();    default void addFirst(E e) {        throw new UnsupportedOperationException();    }    default void addLast(E e) {        throw new UnsupportedOperationException();    }    default E getFirst() {        return this.iterator().next();    }    default E getLast() {        return this.reversed().iterator().next();    }    default E removeFirst() {        var it = this.iterator();        E e = it.next();        it.remove();        return e;    }    default E removeLast() {        var it = this.reversed().iterator();        E e = it.next();        it.remove();        return e;    }}
SequencedCollection继承了Collection接口,同时定义了reversed,提供了addFirst、addLast、getFirst、getLast、removeFirst、removeLast的default实现;List、SequencedSet接口都继承了SequencedCollection接口
public interface SequencedMap<K, V> extends Map<K, V> {    SequencedMap<K, V> reversed();    default Map.Entry<K,V> firstEntry() {        var it = entrySet().iterator();        return it.hasNext() ? new NullableKeyValueHolder<>(it.next()) : null;    }    default Map.Entry<K,V> lastEntry() {        var it = reversed().entrySet().iterator();        return it.hasNext() ? new NullableKeyValueHolder<>(it.next()) : null;    }    default Map.Entry<K,V> pollFirstEntry() {        var it = entrySet().iterator();        if (it.hasNext()) {            var entry = new NullableKeyValueHolder<>(it.next());            it.remove();            return entry;        } else {            return null;        }    }    default Map.Entry<K,V> pollLastEntry() {        var it = reversed().entrySet().iterator();        if (it.hasNext()) {            var entry = new NullableKeyValueHolder<>(it.next());            it.remove();            return entry;        } else {            return null;        }    }    default V putFirst(K k, V v) {        throw new UnsupportedOperationException();    }    default V putLast(K k, V v) {        throw new UnsupportedOperationException();    }    default SequencedSet<K> sequencedKeySet() {        class SeqKeySet extends AbstractMap.ViewCollection<K> implements SequencedSet<K> {            Collection<K> view() {                return SequencedMap.this.keySet();            }            public SequencedSet<K> reversed() {                return SequencedMap.this.reversed().sequencedKeySet();            }            public boolean equals(Object other) {                return view().equals(other);            }            public int hashCode() {                return view().hashCode();            }        }        return new SeqKeySet();    }    default SequencedCollection<V> sequencedValues() {        class SeqValues extends AbstractMap.ViewCollection<V> implements SequencedCollection<V> {            Collection<V> view() {                return SequencedMap.this.values();            }            public SequencedCollection<V> reversed() {                return SequencedMap.this.reversed().sequencedValues();            }        }        return new SeqValues();    }    default SequencedSet<Map.Entry<K, V>> sequencedEntrySet() {        class SeqEntrySet extends AbstractMap.ViewCollection<Map.Entry<K, V>>                implements SequencedSet<Map.Entry<K, V>> {            Collection<Map.Entry<K, V>> view() {                return SequencedMap.this.entrySet();            }            public SequencedSet<Map.Entry<K, V>> reversed() {                return SequencedMap.this.reversed().sequencedEntrySet();            }            public boolean equals(Object other) {                return view().equals(other);            }            public int hashCode() {                return view().hashCode();            }        }        return new SeqEntrySet();    }              }
SequencedMap接口继承了Map接口,它定义了reversed办法,同时提供了firstEntry、lastEntry、pollFirstEntry、pollLastEntry、putFirst、putLast、sequencedKeySet、sequencedValues、sequencedEntrySet办法的默认实现

此次版本的变动:

  • List当初有作为其间接的超级接口,SequencedCollection
  • Deque当初有作为其间接的超级接口,SequencedCollection
  • LinkedHashSet另外实现SequencedSet接口
  • SortedSet当初有作为其间接的超级接口,SequencedSet
  • LinkedHashMap另外实现SequencedMap接口
  • SortedMap当初有作为它的间接超级接口,SequencedMap

另外Collections还提供了工厂办法用于返回不可变类型

Collections.unmodifiableSequencedCollection(sequencedCollection)Collections.unmodifiableSequencedSet(sequencedSet)Collections.unmodifiableSequencedMap(sequencedMap)

JEP 439: Generational ZGC

ZGC分代回收无疑是一个重磅的GC个性,ZGC之前的版本不反对分代回收,此次反对分代回收的话,能够更不便地对年老代进行收集,进步GC性能。目前是分代与非分代都反对,应用分代则通过-XX:+UseZGC-XX:+ZGenerational开启,后续版本将会把分代设置为默认的,而-XX:-ZGenerational用于开启非分代,最初将会破除非分代的反对,届时ZGenerational参数也就没有作用了。

JEP 440: Record Patterns

JDK19的JEP 405: Record Patterns (Preview)将Record的模式匹配作为第一次preview
JDK20的JEP 432: Record Patterns (Second Preview)作为第二次preview
此次在JDK21则作为正式版本公布,应用示例如下
record Point(int x, int y) {}// As of Java 21static void printSum(Object obj) {    if (obj instanceof Point(int x, int y)) {        System.out.println(x+y);    }}enum Color { RED, GREEN, BLUE }record ColoredPoint(Point p, Color c) {}record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}// As of Java 21static void printUpperLeftColoredPoint(Rectangle r) {    if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {         System.out.println(ul.c());    }}static void printColorOfUpperLeftPoint(Rectangle r) {    if (r instanceof Rectangle(ColoredPoint(Point p, Color c),                               ColoredPoint lr)) {        System.out.println(c);    }}

JEP 441: Pattern Matching for switch

在JDK14JEP 305: Pattern Matching for instanceof (Preview)作为preview
在JDK15JEP 375: Pattern Matching for instanceof (Second Preview)作为第二轮的preview
在JDK16JEP 394: Pattern Matching for instanceof转正
JDK17引入JEP 406: Pattern Matching for switch (Preview)
JDK18的JEP 420: Pattern Matching for switch (Second Preview)则作为第二轮preview
JDK19的JEP 427: Pattern Matching for switch (Third Preview)作为第三轮preview
JDK20的JEP 433: Pattern Matching for switch (Fourth Preview)作为第四轮preview
而此次JDK21将Pattern Matching for switch作为正式版本公布,示例如下
// Prior to Java 21static String formatter(Object obj) {    String formatted = "unknown";    if (obj instanceof Integer i) {        formatted = String.format("int %d", i);    } else if (obj instanceof Long l) {        formatted = String.format("long %d", l);    } else if (obj instanceof Double d) {        formatted = String.format("double %f", d);    } else if (obj instanceof String s) {        formatted = String.format("String %s", s);    }    return formatted;}// As of Java 21static String formatterPatternSwitch(Object obj) {    return switch (obj) {        case Integer i -> String.format("int %d", i);        case Long l    -> String.format("long %d", l);        case Double d  -> String.format("double %f", d);        case String s  -> String.format("String %s", s);        default        -> obj.toString();    };}// As of Java 21static void testFooBarNew(String s) {    switch (s) {        case null         -> System.out.println("Oops");        case "Foo", "Bar" -> System.out.println("Great");        default           -> System.out.println("Ok");    }}// As of Java 21static void testStringEnhanced(String response) {    switch (response) {        case null -> { }        case "y", "Y" -> {            System.out.println("You got it");        }        case "n", "N" -> {            System.out.println("Shame");        }        case String s        when s.equalsIgnoreCase("YES") -> {            System.out.println("You got it");        }        case String s        when s.equalsIgnoreCase("NO") -> {            System.out.println("Shame");        }        case String s -> {            System.out.println("Sorry?");        }    }}// As of Java 21static void exhaustiveSwitchWithBetterEnumSupport(CardClassification c) {    switch (c) {        case Suit.CLUBS -> {            System.out.println("It's clubs");        }        case Suit.DIAMONDS -> {            System.out.println("It's diamonds");        }        case Suit.HEARTS -> {            System.out.println("It's hearts");        }        case Suit.SPADES -> {            System.out.println("It's spades");        }        case Tarot t -> {            System.out.println("It's a tarot");        }    }}// As of Java 21sealed interface Currency permits Coin {}enum Coin implements Currency { HEADS, TAILS } static void goodEnumSwitch1(Currency c) {    switch (c) {        case Coin.HEADS -> {    // Qualified name of enum constant as a label            System.out.println("Heads");        }        case Coin.TAILS -> {            System.out.println("Tails");        }    }}static void goodEnumSwitch2(Coin c) {    switch (c) {        case HEADS -> {            System.out.println("Heads");        }        case Coin.TAILS -> {    // Unnecessary qualification but allowed            System.out.println("Tails");        }    }}// As of Java 21static void testNew(Object obj) {    switch (obj) {        case String s when s.length() == 1 -> ...        case String s                      -> ...        ...    }}

JEP 442: Foreign Function & Memory API (Third Preview)

Foreign Function & Memory (FFM) API蕴含了两个incubating API
JDK14的JEP 370: Foreign-Memory Access API (Incubator)引入了Foreign-Memory Access API作为incubator
JDK15的JEP 383: Foreign-Memory Access API (Second Incubator)Foreign-Memory Access API作为第二轮incubator
JDK16的JEP 393: Foreign-Memory Access API (Third Incubator)作为第三轮,它引入了Foreign Linker API (JEP 389)
FFM API在JDK 17的JEP 412: Foreign Function & Memory API (Incubator)作为incubator引入
FFM API在JDK 18的JEP 419: Foreign Function & Memory API (Second Incubator)作为第二轮incubator
JDK19的JEP 424: Foreign Function & Memory API (Preview)则将FFM API作为preview API
JDK20的JEP 434: Foreign Function & Memory API (Second Preview)作为第二轮preview
JDK21则作为第三轮的preview,应用示例
.javac --release 21 --enable-preview ...java --enable-preview ...// 1. Find foreign function on the C library pathLinker linker          = Linker.nativeLinker();SymbolLookup stdlib    = linker.defaultLookup();MethodHandle radixsort = linker.downcallHandle(stdlib.find("radixsort"), ...);// 2. Allocate on-heap memory to store four stringsString[] javaStrings = { "mouse", "cat", "dog", "car" };// 3. Use try-with-resources to manage the lifetime of off-heap memorytry (Arena offHeap = Arena.ofConfined()) {    // 4. Allocate a region of off-heap memory to store four pointers    MemorySegment pointers        = offHeap.allocateArray(ValueLayout.ADDRESS, javaStrings.length);    // 5. Copy the strings from on-heap to off-heap    for (int i = 0; i < javaStrings.length; i++) {        MemorySegment cString = offHeap.allocateUtf8String(javaStrings[i]);        pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);    }    // 6. Sort the off-heap data by calling the foreign function    radixsort.invoke(pointers, javaStrings.length, MemorySegment.NULL, '\0');    // 7. Copy the (reordered) strings from off-heap to on-heap    for (int i = 0; i < javaStrings.length; i++) {        MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);        javaStrings[i] = cString.getUtf8String(0);    }} // 8. All off-heap memory is deallocated hereassert Arrays.equals(javaStrings,                     new String[] {"car", "cat", "dog", "mouse"});  // true

JEP 443: Unnamed Patterns and Variables (Preview)

Unnamed Patterns and Variables反对用_来代替没有应用的变量申明,比方

r instanceof Point _r instanceof ColoredPoint(Point(int x, int _), Color _)if (r instanceof ColoredPoint(_, Color c)) { ... c ... }switch (b) {    case Box(RedBall _), Box(BlueBall _) -> processBox(b);    case Box(GreenBall _)                -> stopProcessing();    case Box(_)                          -> pickAnotherBox();}int acc = 0;for (Order _ : orders) {    if (acc < LIMIT) {         ... acc++ ...    }}while (q.size() >= 3) {    var x = q.remove();    var _ = q.remove();    var _ = q.remove();     ... new Point(x, 0) ...}

JEP 444: Virtual Threads

在JDK19https://openjdk.org/jeps/425)作为第一次preview
在JDK20JEP 436: Virtual Threads (Second Preview)作为第二次preview,此版本java.lang.ThreadGroup被永恒废除
在JDK21版本,Virtual Threads正式公布,与之前版本相比,这次反对了threadlocal,而后也能够通过Thread.Builder来创立,而且也反对threaddump(jcmd <pid> Thread.dump_to_file -format=json <file>)

应用示例

void handle(Request request, Response response) {    var url1 = ...    var url2 = ...     try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {        var future1 = executor.submit(() -> fetchURL(url1));        var future2 = executor.submit(() -> fetchURL(url2));        response.send(future1.get() + future2.get());    } catch (ExecutionException | InterruptedException e) {        response.fail(e);    }} String fetchURL(URL url) throws IOException {    try (var in = url.openStream()) {        return new String(in.readAllBytes(), StandardCharsets.UTF_8);    }}
个别用Executors.newVirtualThreadPerTaskExecutor()是想通过池化技术来缩小对象创立开销,不过因为虚构线程相比平台线程更为"便宜",因此不再须要池化,如果须要管制虚构线程数则能够应用信号量的形式,因此提供了Thread.Builder来间接创立虚构线程,示例如下:
Thread thread = Thread.ofVirtual().name("duke").unstarted(runnable);Thread.startVirtualThread(Runnable) 

JEP 445: Unnamed Classes and Instance Main Methods (Preview)

未命名的类和实例main办法这个个性能够简化hello world示例,不便java新手入门,示例如下

        static void main(String[] args) {            System.out.println("static main with args");        }        static void main() {            System.out.println("static main without args");        }        void main(String[] args) {            System.out.println("main with args");        }        void main() {            System.out.println("main with without args");        }
javac --release 21 --enable-preview Main.javajava --enable-preview Main
其中main办法抉择的优先程序是static的优于非static的,而后有args的优于没有args的

JEP 446: Scoped Values (Preview)

Scoped Values在JDK20的JEP 429: Scoped Values (Incubator)作为Incubator
此次在JDK21作为preview版本
ScopedValue是一种相似ThreadLocal的线程内/父子线程传递变量的更优计划。ThreadLocal提供了一种无需在办法参数上传递通用变量的办法,InheritableThreadLocal使得子线程能够拷贝继承父线程的变量。然而ThreadLocal提供了set办法,变量是可变的,另外remove办法很容易被疏忽,导致在线程池场景下很容易造成内存泄露。ScopedValue则提供了一种不可变、不拷贝的计划,即不提供set办法,子线程不须要拷贝就能够拜访父线程的变量。具体应用如下:
class Server {  public final static ScopedValue<User> LOGGED_IN_USER = ScopedValue.newInstance();   private void serve(Request request) {    // ...    User loggedInUser = authenticateUser(request);    ScopedValue.where(LOGGED_IN_USER, loggedInUser)               .run(() -> restAdapter.processRequest(request));    // ...  }}
通过ScopedValue.where能够绑定ScopedValue的值,而后在run办法里能够应用,办法执行结束自行开释,能够被垃圾收集器回收

JEP 448: Vector API (Sixth Incubator)

JDK16引入了JEP 338: Vector API (Incubator)提供了jdk.incubator.vector来用于矢量计算
JDK17进行改良并作为第二轮的incubatorJEP 414: Vector API (Second Incubator)
JDK18的JEP 417: Vector API (Third Incubator)进行改良并作为第三轮的incubator
JDK19的JEP 426:Vector API (Fourth Incubator)作为第四轮的incubator
JDK20的JEP 438: Vector API (Fifth Incubator)作为第五轮的incubator
而JDK21则作为第六轮的incubator,应用示例如下
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;void vectorComputation(float[] a, float[] b, float[] c) {    int i = 0;    int upperBound = SPECIES.loopBound(a.length);    for (; i < upperBound; i += SPECIES.length()) {        // FloatVector va, vb, vc;        var va = FloatVector.fromArray(SPECIES, a, i);        var vb = FloatVector.fromArray(SPECIES, b, i);        var vc = va.mul(va)                   .add(vb.mul(vb))                   .neg();        vc.intoArray(c, i);    }    for (; i < a.length; i++) {        c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;    }}

JEP 449: Deprecate the Windows 32-bit x86 Port for Removal

废除了对Windows 32-bit x86 (x86-32)的移植,以便后续版本删除

JEP 451: Prepare to Disallow the Dynamic Loading of Agents

对将代理动静加载到正在运行的 JVM 中时收回正告,后续版本将不容许动静加载agent。

在 JDK 9 及更高版本中,能够通过-XX:-EnableDynamicAgentLoading禁止动静加载agent。
在 JDK 21 中,容许动静加载agent,但 JVM 会在产生时收回正告。例如:
WARNING: A {Java,JVM TI} agent has been loaded dynamically (file:/u/bob/agent.jar)WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warningWARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more informationWARNING: Dynamic loading of agents will be disallowed by default in a future release

若要容许工具动静加载agent而不收回正告,用户必须在命令行上应用-XX:+EnableDynamicAgentLoading

JEP 452: Key Encapsulation Mechanism API

Key Encapsulation Mechanism(KEM)是一种古代加密技术,它应用非对称或公钥加密来爱护对称密钥。传统的办法是应用公钥加密一个随机生成的对称密钥,但这须要填充,并且可能难以证实平安。相同,KEM利用公钥的属性派生一个相干的对称密钥,这不须要填充。

此次新增了javax.crypto.KEM、javax.crypto.KEMSpi
package javax.crypto;public class DecapsulateException extends GeneralSecurityException;public final class KEM {    public static KEM getInstance(String alg)        throws NoSuchAlgorithmException;    public static KEM getInstance(String alg, Provider p)        throws NoSuchAlgorithmException;    public static KEM getInstance(String alg, String p)        throws NoSuchAlgorithmException, NoSuchProviderException;    public static final class Encapsulated {        public Encapsulated(SecretKey key, byte[] encapsulation, byte[] params);        public SecretKey key();        public byte[] encapsulation();        public byte[] params();    }    public static final class Encapsulator {        String providerName();        int secretSize();           // Size of the shared secret        int encapsulationSize();    // Size of the key encapsulation message        Encapsulated encapsulate();        Encapsulated encapsulate(int from, int to, String algorithm);    }    public Encapsulator newEncapsulator(PublicKey pk)            throws InvalidKeyException;    public Encapsulator newEncapsulator(PublicKey pk, SecureRandom sr)            throws InvalidKeyException;    public Encapsulator newEncapsulator(PublicKey pk, AlgorithmParameterSpec spec,                                        SecureRandom sr)            throws InvalidAlgorithmParameterException, InvalidKeyException;    public static final class Decapsulator {        String providerName();        int secretSize();           // Size of the shared secret        int encapsulationSize();    // Size of the key encapsulation message        SecretKey decapsulate(byte[] encapsulation) throws DecapsulateException;        SecretKey decapsulate(byte[] encapsulation, int from, int to,                              String algorithm)                throws DecapsulateException;    }    public Decapsulator newDecapsulator(PrivateKey sk)            throws InvalidKeyException;    public Decapsulator newDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)            throws InvalidAlgorithmParameterException, InvalidKeyException;}
它次要是提供了newEncapsulator、newDecapsulator办法,应用示例如下
// Receiver sideKeyPairGenerator g = KeyPairGenerator.getInstance("ABC");KeyPair kp = g.generateKeyPair();publishKey(kp.getPublic());// Sender sideKEM kemS = KEM.getInstance("ABC-KEM");PublicKey pkR = retrieveKey();ABCKEMParameterSpec specS = new ABCKEMParameterSpec(...);KEM.Encapsulator e = kemS.newEncapsulator(pkR, specS, null);KEM.Encapsulated enc = e.encapsulate();SecretKey secS = enc.key();sendBytes(enc.encapsulation());sendBytes(enc.params());// Receiver sidebyte[] em = receiveBytes();byte[] params = receiveBytes();KEM kemR = KEM.getInstance("ABC-KEM");AlgorithmParameters algParams = AlgorithmParameters.getInstance("ABC-KEM");algParams.init(params);ABCKEMParameterSpec specR = algParams.getParameterSpec(ABCKEMParameterSpec.class);KEM.Decapsulator d = kemR.newDecapsulator(kp.getPrivate(), specR);SecretKey secR = d.decapsulate(em);// secS and secR will be identical

JEP 453: Structured Concurrency (Preview)

在JDK19的JEP 428: Structured Concurrency (Incubator)作为第一次incubator
在JDK20的JEP 437: Structured Concurrency (Second Incubator)作为第二次incubator
此次在JDK21则作为preview,应用示例如下
Response handle() throws ExecutionException, InterruptedException {    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {        Supplier<String>  user  = scope.fork(() -> findUser());        Supplier<Integer> order = scope.fork(() -> fetchOrder());        scope.join()            // Join both subtasks             .throwIfFailed();  // ... and propagate errors        // Here, both subtasks have succeeded, so compose their results        return new Response(user.get(), order.get());    }}

细项解读

下面列出的是大方面的个性,除此之外还有一些api的更新及废除,次要见JDK 21 Release Notes,这里举几个例子。

增加项

  • Math.clamp() and StrictMath.clamp() Methods (JDK-8301226)
  • New String indexOf(int,int,int) and indexOf(String,int,int) Methods to Support a Range of Indices (JDK-8302590)
  • New splitWithDelimiters() Methods Added to String and java.util.regex.Pattern (JDK-8305486)
  • System.exit() and Runtime.exit() Logging (JDK-8301627)
  • The java.net.http.HttpClient Is Now AutoCloseable (JDK-8267140)
  • New StringBuilder and StringBuffer repeat Methods (JDK-8302323)
  • Last Resort G1 Full GC Moves Humongous Objects (JDK-8191565)

移除项

  • Removed SECOM Trust System's RootCA1 Root Certificate (JDK-8295894)
  • java.io.File's Canonical Path Cache Is Removed (JDK-8300977)
  • Removal of the java.compiler System Property (JDK-8041676)
  • The java.lang.Compiler Class Has Been Removed (JDK-8205129)
  • Remove the JAR Index Feature (JDK-8302819)
  • Removal of G1 Hot Card Cache (JDK-8225409)
  • Obsolete Legacy HotSpot Parallel Class Loading Workaround Option -XX:+EnableWaitForParallelLoad Is Removed (JDK-8298469)
  • The MetaspaceReclaimPolicy Flag has Been Obsoleted (JDK-8302385)

废除项

  • Deprecate GTK2 for Removal (JDK-8280031)
  • Deprecate JMX Subject Delegation and the JMXConnector.getMBeanServerConnection(Subject) Method for Removal (JDK-8298966)

重要bug修复

  • Error Computing the Amount of Milli- and Microseconds between java.time.Instants (JDK-8307466)
  • Disallow Extra Semicolons Between "import" Statements (JDK-8027682)

已知问题

  • JVM May Crash or Malfunction When Using ZGC and Non-Default ObjectAlignmentInBytes (JDK-8312749)
  • Validations on ZIP64 Extra Fields (JDK-8313765)
  • java.util.regex.MatchResult Might Throw StringIndexOutOfBoundsException on Regex Patterns Containing Lookaheads and Lookbehinds (JDK-8132995)
  • JVM May Hang When Using Generational ZGC if a VM Handshake Stalls on Memory (JDK-8311981)

其余事项

  • ObjectInputStream::readObject() Should Handle Negative Array Sizes without Throwing NegativeArraySizeExceptions (JDK-8306461)
  • File::listRoots Changed to Return All Available Drives on Windows (JDK-8208077)
  • Thread.sleep(millis, nanos) Is Now Able to Perform Sub-Millisecond Sleeps (JDK-8305092)
  • FileChannel.transferFrom Extends File if Called to Transfer Bytes to the File (JDK-8303260)
  • Clarification of the Default Charset Initialization with file.encoding (JDK-8300916)
  • java.util.Formatter May Return Slightly Different Results on double and float (JDK-8300869)
  • JVM TI ThreadStart and ThreadEnd Events Not Sent for Virtual Threads (JDK-8307399)
  • Add final Keyword to Some Static Methods (JDK-8302696)

小结

Java21次要有如下几个个性

  • JEP 430: String Templates (Preview)
  • JEP 431: Sequenced Collections
  • JEP 439: Generational ZGC
  • JEP 440: Record Patterns
  • JEP 441: Pattern Matching for switch
  • JEP 442: Foreign Function & Memory API (Third Preview)
  • JEP 443: Unnamed Patterns and Variables (Preview)
  • JEP 444: Virtual Threads
  • JEP 445: Unnamed Classes and Instance Main Methods (Preview)
  • JEP 446: Scoped Values (Preview)
  • JEP 448: Vector API (Sixth Incubator)
  • JEP 449: Deprecate the Windows 32-bit x86 Port for Removal
  • JEP 451: Prepare to Disallow the Dynamic Loading of Agents
  • JEP 452: Key Encapsulation Mechanism API
  • JEP 453: Structured Concurrency (Preview)

    其中JEP 439: Generational ZGC及JEP 444: Virtual Threads应属于重磅级的个性,而JEP 430: String Templates (Preview)、JEP 431: Sequenced Collections、JEP 440: Record Patterns及JEP 441: Pattern Matching for switch则在语言表达力层面上有了加强
    另外java21是继JDK 17之后最新的长期反对(LTS)版本,将取得至多8年的反对。

doc

  • JDK 21 Features
  • JDK 21 Release Notes
  • Consolidated JDK 21 Release Notes
  • Java SE 21 deprecated-list
  • The Arrival of Java 21
  • JDK 21 G1/Parallel/Serial GC changes
  • Java 21, the Next LTS Release, Delivers Virtual Threads, Record Patterns and Pattern Matching
  • JDK 21 and JDK 22: What We Know So Far
  • Java 21 New Features: “The ZGC is generational and will further improve performance for suitable applications”
  • Java 21 is Available Today, And It’s Quite the Update