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

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

版本号

java -versionopenjdk version "20" 2023-03-21OpenJDK Runtime Environment (build 20+36-2344)OpenJDK 64-Bit Server VM (build 20+36-2344, mixed mode, sharing)
从version信息能够看出是build 20+36

个性列表

JEP 429: Scoped Values (Incubator)

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 432: Record Patterns (Second Preview)

JDK19的JEP 405: Record Patterns (Preview)将Record的模式匹配作为第一次preview
JDK20则作为第二次preview
  • 针对嵌套record的推断,能够这样

    record Point(int x, int y) {}enum Color { RED, GREEN, BLUE }record ColoredPoint(Point p, Color c) {}record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}static void printColorOfUpperLeftPoint(Rectangle r) {  if (r instanceof Rectangle(ColoredPoint(Point p, Color c),                             ColoredPoint lr)) {      System.out.println(c);  }}
  • 整体而言,模式匹配有如下几种:

    Pattern:TypePatternParenthesizedPatternRecordPatternTypePattern:LocalVariableDeclarationParenthesizedPattern:( Pattern )RecordPattern:ReferenceType RecordStructurePatternRecordStructurePattern:( [ RecordComponentPatternList ] )RecordComponentPatternList : Pattern { , Pattern }
  • 针对泛型推断

    record Box<T>(T t) {}static void test1(Box<String> bo) {  if (bo instanceof Box<String>(var s)) {      System.out.println("String " + s);  }}

    也反对嵌套

    static void test3(Box<Box<String>> bo) {  if (bo instanceof Box<Box<String>>(Box(var s))) {          System.out.println("String " + s);  }}

JEP 433: Pattern Matching for switch (Fourth Preview)

在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作为第四轮preview
自第三次预览以来的次要变动是:
  • 针对枚举类型呈现无奈匹配的时候抛出MatchException而不是IncompatibleClassChangeError
  • 开关标签的语法更简略
  • switch当初反对record泛型的推断

以前针对null值switch会抛出异样,须要非凡解决

static void testFooBar(String s) {    if (s == null) {        System.out.println("Oops!");        return;    }    switch (s) {        case "Foo", "Bar" -> System.out.println("Great");        default           -> System.out.println("Ok");    }}

当初能够间接switch

static void testFooBar(String s) {    switch (s) {        case null         -> System.out.println("Oops");        case "Foo", "Bar" -> System.out.println("Great");        default           -> System.out.println("Ok");    }}

case when的反对,以前这么写

class Shape {}class Rectangle extends Shape {}class Triangle  extends Shape { int calculateArea() { ... } }static void testTriangle(Shape s) {    switch (s) {        case null:            break;        case Triangle t:            if (t.calculateArea() > 100) {                System.out.println("Large triangle");                break;            }        default:            System.out.println("A shape, possibly a small triangle");    }}

当初能够这么写

static void testTriangle(Shape s) {    switch (s) {        case null ->             { break; }        case Triangle t        when t.calculateArea() > 100 ->            System.out.println("Large triangle");        case Triangle t ->            System.out.println("Small triangle");        default ->            System.out.println("Non-triangle");    }}

针对record泛型的类型推断:

record MyPair<S,T>(S fst, T snd){};static void recordInference(MyPair<String, Integer> pair){    switch (pair) {        case MyPair(var f, var s) ->             ... // Inferred record Pattern MyPair<String,Integer>(var f, var s)        ...    }}

JEP 434: Foreign Function & Memory API (Second 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作为第二轮preview

应用示例

 javac --release 20 --enable-preview ... and 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.openConfined()) {    // 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 436: Virtual Threads (Second Preview)

在JDK19https://openjdk.org/jeps/425)作为第一次preview
在JDK20作为第二次preview,此版本java.lang.ThreadGroup被永恒废除

应用示例

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);    }}

JEP 437: Structured Concurrency (Second Incubator)

在JDK19JEP 428: Structured Concurrency (Incubator)作为第一次incubator
在JDK20作为第二次incubator

JEP 438: Vector API (Fifth 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
JDK19JEP 426:Vector API (Fourth Incubator)作为第四轮的incubator
JDK20作为第五轮的incubator

细项解读

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

增加项

  • Support Unicode 15.0 Update Unicode Data Files to 15.0.0
  • Add GarbageCollectorMXBean for Remark and Cleanup Pause Time in G1 JDK-8297247

移除项

  • Thread.suspend/resume Changed to Throw UnsupportedOperationException JDK-8249627
  • Thread.Stop Changed to Throw UnsupportedOperationException JDK-8289610
  • Improved Control of G1 Concurrent Refinement Threads JDK-8137022

    以下这些参数将来版本移除
    -XX:-G1UseAdaptiveConcRefinement-XX:G1ConcRefinementGreenZone=buffer-count-XX:G1ConcRefinementYellowZone=buffer-count-XX:G1ConcRefinementRedZone=buffer-count-XX:G1ConcRefinementThresholdStep=buffer-count-XX:G1ConcRefinementServiceIntervalMillis=msec

废除项

残缺列表见Java SE 20 deprecated-list

  • java.net.URL Constructors Are Deprecated JDK-8294241

    URL的结构器被废除,能够应用URL::of(URI, URLStreamHandler)工厂办法代替

已知问题

  • java.lang.Float.floatToFloat16 and java.lang.Float.float16ToFloat May Return Different NaN Results when Optimized by the JIT Compiler (JDK-8302976, JDK-8289551, JDK-8289552)

    JDK20引入了java.lang.Float.floatToFloat16及java.lang.Float.float16ToFloat办法,在JIT编译优化时可能会返回不同的Nan后果,能够应用如下参数禁用JIT对此的优化
    -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_floatToFloat16,_float16ToFloat

其余事项

  • Disabled TLS_ECDH_* Cipher Suites (JDK-8279164)

    TLS_ECDH_* cipher suites默认被禁用了
  • HTTP Response Input Streams Will Throw an IOException on Interrupt (JDK-8294047)
  • HttpClient Default Keep Alive Time is 30 Seconds (JDK-8297030)

    http1.1及http2的闲暇连贯的超时工夫从1200秒改为30秒

小结

Java20次要有如下几个个性

  • JEP 429: Scoped Values (Incubator)
  • JEP 432: Record Patterns (Second Preview)
  • JEP 433: Pattern Matching for switch (Fourth Preview)
  • JEP 434: Foreign Function & Memory API (Second Preview)
  • JEP 436: Virtual Threads (Second Preview)
  • JEP 437: Structured Concurrency (Second Incubator)
  • JEP 438: Vector API (Fifth Incubator)

doc

  • JDK 20 Features
  • JDK 20 Release Notes
  • Consolidated JDK 20 Release Notes
  • Java SE 20 deprecated-list
  • The Arrival of Java 20
  • JDK 20 G1/Parallel/Serial GC changes
  • Java 20 Delivers Features for Projects Amber, Loom and Panama
  • Java 20: a faster future is Looming
  • JDK 20 Security Enhancements
  • Project Loom’s Scoped Values: The Most Interesting New Java 20 Feature