20240327
20240312
20231227
Java新的结构化并行模式入门指南-51CTO.COM结构化并发是Java中使用多线程的一种新方式。它允许开发人员在充分利用传统线程和虚拟线程的同时考虑逻辑组中的工作。结构化并发出现在Java 21的预览版中,它是决定Java未来的一个关键方面,所以现在是开始使用它的好时机。https://www.51cto.com/article/777541.htmlGet started with Java's new structured concurrency model | InfoWorldJava has a powerful new concurrency model, and it works with both traditional and virtual threads. Here's a first look at structured concurrency.https://www.infoworld.com/article/3711361/get-started-with-javas-new-structured-concurrency-model.html
20231220
20231218
我认为 Loom 项目将会消灭响应式编程
20231011
Java 21 虚拟线程详解虚拟线程入门介绍与使用指南https://mp.weixin.qq.com/s/wGsdLju18vLbaeN4PznUzA
什么是Java Record?
Java Record是一种紧凑、不可变且自动生成常见方法的类定义方式。使用record关键字定义的类会自动根据声明的字段生成对应的私有字段和公共访问器方法(getter方法),从而允许我们方便地获取和修改记录中的属性值。此外,Records还自动生成了默认的equals()、hashCode()和toString()方法,大大减少了样板代码的书写。
优势和用法
- 简洁性:通过使用Records,可以以更少的代码量定义数据类,避免了繁琐的样板代码。相较于传统的POJO类,Records更加精炼,只需要列出字段即可,而无需手动编写访问器方法。
- 不可变性:Record类的字段在实例化后无法修改,确保了不可变性。这有助于编写更安全且易于理解的代码,避免了意外的状态变化。
- 自动生成的方法:Record类会自动生成默认的equals()、hashCode()和toString()等方法。equals()和hashCode()方法基于定义的字段进行比较,toString()方法提供了记录的简洁字符串表示形式。这些方法可以直接使用,并且在不同的记录对象之间进行比较时非常方便。
- 适用场景:Java Record适用于表示简单的数据结构,如DTO、领域对象或一些不可变的值对象。对于复杂的业务逻辑或需要特定行为的类,传统的类定义方式可能更适合。
下面是一个简单的例子来展示Java Record的用法:
复制
record Person(String name, int age) {
// 可以在record内部添加其他方法或构造函数
}
public class Main {
public static void main(String[] args) {
Person person = new Person("John", 25);
System.out.println(person.name()); // 访问name字段
System.out.println(person.age()); // 访问age字段
System.out.println(person); // 自动生成的toString()方法
Person person2 = new Person("John", 25);
System.out.println(person.equals(person2)); // 自动生成的equals()方法
}
}
在上述代码中,我们通过定义一个Person记录类型来表示一个人的信息。我们可以轻松地访问记录中的属性,并使用自动生成的toString()和equals()方法。
7.2 Records(记录类型)
Records(记录类型)是JDK 14引入的一项新特性,它简化了创建不可变(immutable)数据对象的过程。通过使用record关键字,可以定义一个记录类型,该类型自动生成了一些标准的方法,如构造函数、getter方法、equals()、hashCode()和toString()等方法。以下是一个使用记录类型的示例:
public record Person(String name, int age) {
// 自动生成了构造函数和getter方法
}
// 创建记录类型的实例
Person person = new Person("John Doe", 30);
// 访问记录类型的属性
String name = person.name();
int age = person.age();
// 自动生成的toString()方法
System.out.println(person);
在上述示例中,使用record关键字定义了一个名为Person的记录类型,它有两个属性:name和age。通过定义记录类型,我们可以避免手动编写构造函数和getter方法,这些方法会自动生成并与记录类型绑定。我们可以使用记录类型的构造函数来创建实例,然后通过自动生成的getter方法访问属性。例如,person.name()返回记录类型实例的name属性值。此外,记录类型还提供了自动生成的equals()和hashCode()方法,用于比较记录类型的相等性和生成哈希码。同时,它还提供了自动生成的toString()方法,用于以字符串形式表示记录类型的内容。需要注意的是,记录类型是不可变的,即一旦创建,就不能修改其属性的值。如果需要修改属性,需要创建一个新的记录类型实例。记录类型的引入简化了创建简单数据对象的过程,减少了样板代码,提高了代码的可读性和可维护性,尤其适用于那些只包含数据的简单对象。
-
record是JDK 14 中的预览语言功能,主要用于声明类,用于增强 Java 编程语言。
-
java14引入的java.lang.Record,是所有的record类的共同超类。
-
record类的语义声明简单、透明,同时自动派生出许多标准成员:
-
-
生成private final 修饰的组件字段。
-
提供组件字段的读取访问方法。
-
提供一个公共构造函数。
-
提供equal和hashCode。
-
提供toString方法。
-
基本使用:
record Rectangle(double length, double width) { }
等价于如下写法:
public final class Rectangle {
//private final 修饰的成员变量
private final double length;
private final double width;
//全参构造器
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
//读取方法
double length() { return this.length; }
double width() { return this.width; }
//重写equals和hashCode
public boolean equals...
public int hashCode...
// 实现toString方法
// including their names.
public String toString() {...}
}
注意: 生成的成员的属性都是private final修饰的,且只提供读取访问器。
百度安全验证 java17语言更新——Record Classes
record 和密封类 与代数数据类型的关系:
This is a type where we specify the shape of each of the elements. Wikipedia has a thorough discussion. "Algebraic" refers to the property that an Algebraic Data Type is created by "algebraic" operations. The "algebra" here is "sums" and "products":
"sum" is alternation (A | B, meaning A or B but not both)
"product" is combination (A B, meaning A and B together)
Examples:
data Pair = P Int Double
is a pair of numbers, an Int and a Double together. The tag P is used (in constructors and pattern matching) to combine the contained values into a single structure that can be assigned to a variable.data Pair = I Int | D Double
is just one number, either an Int or else a Double. In this case, the tags I and D are used (in constructors and pattern matching) to distinguish between the two alternatives.
Algebraic data type - HaskellWikihttps://wiki.haskell.org/Algebraic_data_type
c99 中的代数类型
GitHub - Hirrolot/datatype99: Algebraic data types for C99
JEP 395: Recordshttps://openjdk.org/jeps/395
JEP 409: Sealed Classeshttps://openjdk.org/jeps/409
这篇文章有例子
JDK8-JDK17新特性总结4万字长文详细介绍从JDK8到JDK17的新特性https://mp.weixin.qq.com/s/41AyZMWvvXTKZ2Zgk7h8gg
20230613
JDK 21 中的结构化并发旨在通过引入用于结构化并发的 API 来简化并发编程。这种方法将在不同线程中运行的相关任务组视为一个工作单元,从而简化错误处理和取消,提高可靠性并增强可观察性。让我们看一个例子:
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());
}
//...
}
此代码创建一个新的 StructuredTaskScope
并使用它来派生两个子任务:一个执行 findUser()
,另一个执行 fetchOrder()
。两个子任务完成后,它会使用两个子任务的结果创建一个新的 Response
。
String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan"); // true
Java 通过 Record Pattern 得到提升,实现更具表现力的编码
虚拟线程:大规模 Java 应用程序的新基础
Java 8 - 使用 lambda 推断泛型返回类型 - IT工具网https://www.coder.work/article/1337661
JEP咖啡屋13[熟肉]-Loom 结构化并发编程全解https://mp.weixin.qq.com/s/8DfziSujAayOJOqepbtTUw
我试图在 Java 8 中的一些高阶函数中保留来自 lambda 表达式的返回类型的通用类型信息。我已将我的实际代码简化为这个测试用例。问题不是我期望代码完全做什么,而是我期望泛型类型R
推断为 java.lang.String
并通过函数调用进行。
import java.util.function.Function;
public class AdamTest {
public final static void main(final String args[]) {
final AdamTest adamTest = new AdamTest();
final String s = adamTest.thing2(7).apply(i -> i.toString());
System.out.println(s);
}
private <R> R fn1(final Function<Integer, R> op) {
return op.apply(10);
}
private <R> Function<Function<Integer, R>, R> thing2(final Integer val) {
return fn1(i -> new Function<Function<Integer, R>, R>() {
@Override
public R apply(Function<Integer, R> op) {
return op.apply(val * i);
}
}
);
}
}
目前,由于此行
final String s = adamTest.thing2(7).apply(i -> i.toString());
,此代码无法编译.我想我的类型边界有一些微妙的错误,因为编译器似乎无法推断 thing2(7).apply
的返回类型和报告 Object
而不是 String
这是我所希望的。如何获得正确的泛型类型边界,以便正确的返回类型,即
java.lang.String
是 推断 由编译器?
最佳答案
如前所述,这些语句是从左到右评估的。
要强制编译器使用正确的类型,您可以简单地将其写为
final String s = adamTest.<String>thing2(7).apply(String::valueOf);
编辑:根据评论,可以用方法引用替换 lambda 表达式(看起来更干净)
虚拟线程
虚拟线程是一种替代实现,java.lang.Thread
它将它们的堆栈帧存储在 Java 的垃圾收集堆中,而不是存储在操作系统分配的单片内存块中。我们不必猜测一个线程可能需要多少堆栈空间,或者对所有线程进行一刀切的估计;虚拟线程的内存占用开始时只有几百字节,并随着调用堆栈的扩展和收缩而自动扩展和收缩。
操作系统只知道平台线程,它仍然是调度单元。为了在虚拟线程中运行代码,Java 运行时通过将其安装在某个平台线程(称为载体线程)上来安排它运行。挂载虚拟线程意味着将所需的堆栈帧从堆中临时复制到载体线程的堆栈中,并在挂载时借用载体堆栈。
当在虚拟线程中运行的代码会因 IO、锁定或其他资源可用性而阻塞时,它可以从载体线程中卸载,并且复制的任何修改的堆栈帧都将返回到堆中,从而释放载体线程以进行其他操作(例如就像运行另一个虚拟线程一样。)JDK 中几乎所有的阻塞点都已经过调整,因此当在虚拟线程上遇到阻塞操作时,虚拟线程会从其载体上卸载而不是阻塞。
在载体线程上挂载和卸载虚拟线程是 Java 代码完全不可见的实现细节。Java代码无法观察到当前载体的身份(调用Thread::currentThread
总是返回虚拟线程);ThreadLocal
载体线程的值对已安装的虚拟线程不可见;载体的堆栈帧不会出现在虚拟线程的异常或线程转储中。在虚拟线程的生命周期中,它可能在许多不同的载体线程上运行,但是任何取决于线程标识的东西,例如锁定,都会看到它在哪个线程上运行的一致画面。
虚拟线程之所以如此命名,是因为它们与虚拟内存共享特性。使用虚拟内存,应用程序会产生一种错觉,即他们可以访问整个内存地址空间,而不受可用物理内存的限制。硬件通过根据需要将丰富的虚拟内存临时映射到稀缺的物理内存来完成这种错觉,当其他一些虚拟页面需要该物理内存时,旧的内容首先被分页到磁盘。同样,虚拟线程既便宜又丰富,根据需要共享稀缺和昂贵的平台线程,不活动的虚拟线程堆栈被“分页”到堆中。
虚拟线程具有相对较少的新 API 表面。有几种创建虚拟线程的新方法(例如,Thread::ofVirtual),但创建后,它们是普通Thread
对象,并且表现得像我们已经知道的线程。现有的 API,如Thread::currentThread
、ThreadLocal
、中断、堆栈遍历等,在虚拟线程上的工作方式与在平台线程上的工作方式完全相同,这意味着我们可以在虚拟线程上自信地运行现有代码。
Virtual Threads: New Foundations for High-Scale Java ApplicationsVirtual threads are a lightweight implementation of Java threads, delivered as a preview feature in Java 19.https://www.infoq.com/articles/java-virtual-threads/
结构化并发
结构化并发是 Java 19 中的一个孵化功能。
结构化并发的目的是简化多线程和并行编程。它将在不同线程中运行的多个任务视为一个工作单元,简化了错误处理和任务取消,同时提高了可靠性和可观测性。这有助于避免线程泄漏和取消延迟等问题。作为一个孵化功能,在稳定过程中可能会经历进一步的变更。
我们考虑如下这个使用java.util.concurrent.ExecutorService
的样例。
void handleOrder() throws ExecutionException, InterruptedException {
try (var esvc = new ScheduledThreadPoolExecutor(8)) {
Future<Integer> inventory = esvc.submit(() -> updateInventory());
Future<Integer> order = esvc.submit(() -> updateOrder());
int theInventory = inventory.get(); // Join updateInventory
int theOrder = order.get(); // Join updateOrder
System.out.println("Inventory " + theInventory + " updated for order " + theOrder);
}
}
我们希望updateInventory()
和updateOrder()
这两个子任务能够并发执行。每一个任务都可以独立地成功或失败。理想情况下,如果任何一个子任务失败,handleOrder()
方法都应该失败。然而,如果某个子任务发生失败的话,事情就会变得难以预料。
-
设想一下,
updateInventory()
失败并抛出了一个异常。那么,handleOrder()
方法在调用invent.get()
时将会抛出异常。到目前为止,还没有什么大问题,但updateOrder()
呢?因为它在自己的线程上运行,所以它可能会成功完成。但是现在我们就有了一个库存和订单不匹配的问题。假设updateOrder()
是一个代价高昂的操作。在这种情况下,我们白白浪费了资源,不得不编写某种防护逻辑来撤销对订单所做的更新,因为我们的整体操作已经失败。 -
假设
updateInventory()
是一个代价高昂的长时间运行操作,而updateOrder()
抛出一个错误。即便updateOrder()
抛出了错误,handleOrder()
任务依然会在inventory.get()
方法上阻塞。理想情况下,我们希望handleOrder()
任务在updateOrder()
发生故障时取消updateInventory()
,这样就不会浪费时间了。 -
如果执行
handleOrder()
的线程被中断,那么中断不会被传播到子任务中。在这种情况下,updateInventory()
和updateOrder()
会泄露并继续在后台运行。
对于这些场景,我们必须小心翼翼地编写变通方案和故障防护措施,把所有的职责推到了开发人员身上。
我们可以使用下面的代码,用结构化并发实现同样的功能。
void handleOrder() throws ExecutionException, InterruptedException {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<Integer> inventory = scope.fork(() -> updateInventory());
Future<Integer> order = scope.fork(() -> updateOrder());
scope.join(); // Join both forks
scope.throwIfFailed(); // ... and propagate errors
// Here, both forks have succeeded, so compose their results
System.out.println("Inventory " + inventory.resultNow() + " updated for order " + order.resultNow());
}
}
与之前使用ExecutorService
的样例不同,我们现在使用StructuredTaskScope
来实现同样的结果,并将子任务的生命周期限制在词法的作用域内,在本例中,也就是 try-with-resources 语句体内。这段代码更易读,而且意图也很清楚。StructuredTaskScope
还自动确保以下行为:
-
基于短路的错误处理:如果
updateInventory()
或updateOrder()
失败,另一个将被取消,除非它已经完成。这是由ShutdownOnFailure()
实现的取消策略来管理的,我们还可以使用其他策略。 -
取消传播:如果运行
handleOrder()
的线程在调用join()
之前或调用过程中被中断的话,当该线程退出作用域时,两个分支(fork)都会被自动取消。 -
可观察性:线程转储文件将清楚地显示任务层次,运行
updateInventory()
和updateOrder()
的线程被显示为作用域的子线程。
虚拟线程实现还有如下几个注意事项:
-
在代码、运行时、调试器和剖析器(profiler)中,它是一个
Thread
。 -
它是一个 Java 实体,并不是对原生线程的封装。
-
创建和阻塞它们是代价低廉的操作。
-
它们不应该放到池中。
-
虚拟线程使用了一个基于任务窃取(work-stealing)的
ForkJoinPool
调度器。 -
可以将可插拔的调度器用于异步编程中。
-
虚拟线程会有自己的栈内存。
-
虚拟线程的 API 与平台线程非常相似,因此更容易使用或移植。
在 Project Loom 的支持下,提议在线程内和跨线程共享不可变数据。这比线程局部变量更受欢迎,尤其是在使用大量虚拟线程时。
在线程内和跨线程共享不可变数据。这比线程局部变量更受欢迎,尤其是在使用大量虚拟线程时。
在这个 JEP 中,代替ThreadLocal,提出了一种新类型ExtentLocal。范围局部变量允许在大型程序中的组件之间安全地共享数据。通常,它被声明为 final 静态字段,因此可以很容易地从许多组件中访问它。它只写一次,不可变,并且仅在线程执行期间的有限时间内可用。
通常,大型 Java 程序由共享数据的多个组件组成。例如,Web 框架可能需要服务器和数据访问组件。用户身份验证和授权对象需要跨组件共享。服务器组件可以创建对象,然后将其作为参数传递给方法调用。这种传递参数的方法并不总是可行的,因为服务器组件可能首先调用不受信任的用户代码。ThreadLocal表示可用的替代方案。考虑以下使用ThreadLocal的示例:
在上面的示例中,PRINCIPAL对象表示ThreadLocal ,在Server类中实例化,数据最初存储在该类中。然后,它稍后在DBAccess类中使用。使用ThreadLocal变量,当服务器组件调用用户代码,而用户代码调用数据访问组件时,我们避免了服务器组件调用PRINCIPAL作为方法参数。
尽管这种方法看起来很有吸引力,但它有许多无法避免的设计缺陷:
不受约束的可变性:每个线程ThreadLocal 局部变量都是可变的。这意味着可以随时调用变量的get()和set()方法。ThreadLocal API 支持这一点。数据可以在组件之间沿任一方向流动的通用通信模型会导致类似意大利面条的数据流。
无限生命周期:内存泄漏可能发生在依赖于线程局部变量不受限制的可变性的程序中。因为开发人员经常忘记调用remove(),所以每个线程的数据通常会保留比必要的更长的时间。如果每个线程数据的写入和读取发生在线程执行期间的有限时间范围内,那将是更可取的,从而消除了泄漏的可能性。
昂贵的继承:当使用大量线程时,线程局部变量的开销可能会增加,因为子线程可以从父线程继承线程局部变量。这会增加显着的内存占用。
随着虚拟线程(JEP 425)的可用性,线程局部变量的问题变得更加紧迫。多个虚拟线程共享相同的载体线程。这允许我们创建大量的虚拟线程。这意味着 Web 框架可以为每个请求提供自己的虚拟线程,同时处理数千或数百万个请求。
简而言之,线程局部变量比共享数据通常所需的复杂性更高,并且带来无法避免的高成本。
这个 JEP 旨在用ThreadLocal解决所有这些问题,并提供更好的替代方案。
这些新功能中的四 (4) 个被归类在核心 Java 库下:
- JEP 424:外部函数和内存 API(预览版)
- JEP 425:虚拟线程(预览版)
- JEP 426:Vector API(第四个孵化器)
- JEP 428:结构化并发(孵化器)
这些新功能中的两 (2) 个归类在Java 规范下:
- JEP 405:记录模式(预览)
- JEP 427:开关的模式匹配(第三次预览)
最后,一 (1) 个单独的功能被归类在Hotspot Compiler下:
- JEP 422:Linux/RISC-V 端口
我们检查了这些新功能,并包括它们属于四个主要 Java 项目(Amber、Loom、Panama和Valhalla)支持的地方,这些项目旨在孵化一系列组件,以通过策划合并最终包含在 JDK 中。
琥珀计划
JEP 405,Record Patterns (Preview) ,建议使用记录模式来增强语言以解构记录值。记录模式可以与类型模式结合使用,以“实现强大的、声明性的和可组合的数据导航和处理形式”。switch
最近通过 JEP 406,用于开关的模式匹配(预览版)(在 JDK 17 中提供)和 JEP 420,用于开关的模式匹配(第二次预览版)(在 JDK 18 中提供)扩展了类型模式以用于案例标签。有关 JEP 405 的更多详细信息,请参阅此 InfoQ新闻报道。
JEP 427, Pattern Matching for switch (Third Preview),根据前两轮预览的反馈加入了增强功能:JEP 406, Pattern Matching for switch (Preview)(在 JDK 17 中提供)和 JEP 420, Pattern Matching for switch(第二次预览版)(在 JDK 18 中提供)。JEP 420 的变化包括:受保护的模式被替换为块中的when
子句switch
;and runtime semantics of a pattern switch are more closely aligned with legacy switch semantics when the value of the selector expression is null
.
项目织机
JEP 425,Virtual Threads (Preview),引入了虚拟线程,轻量级线程,显着减少了 Java 平台编写、维护和观察高吞吐量并发应用程序的工作量。有关 JEP 425 的更多详细信息,请参阅 InfoQ新闻报道和甲骨文 Java 平台组 Java 开发倡导者José Paumard的JEP Café屏幕截图。
JEP 428,结构化并发(孵化器),建议通过引入一个库将在不同线程中运行的多个任务视为单个工作单元来简化多线程编程。这可以简化错误处理和取消,提高可靠性并增强可观察性。有关 JEP 428 的更多详细信息,请参阅此 InfoQ新闻报道。
巴拿马项目
JEP 424,Foreign Function & Memory API (Preview)引入了一个 API,用于 Java 应用程序,通过有效地调用外部函数和安全访问不受 JVM 管理的外部内存,与 Java 运行时之外的代码和数据进行互操作。该 JEP 演进:JEP 419,Foreign Function & Memory API (Second Incubator),在 JDK 18 中交付;和 JEP 412,外部函数和内存 API(孵化器),在 JDK 17 中提供;结合基于 Java 社区反馈的改进。
JEP 426, Vector API (Fourth Incubator),针对前三轮孵化器的反馈进行了增强:JEP 417, Vector API (Third Incubator)(在 JDK 18 中提供),JEP 414,Vector API(第二个孵化器)(在 JDK 17 中提供)和 JEP 338,Vector API(孵化器),作为 JDK 16 中的孵化器模块提供。JEP 426 建议增强 Vector API 以从MemorySegment
JEP 424 定义的外部函数加载和存储向量& 内存 API(预览版)。
热点编译器
JEP 422,Linux/RISC-V Port,建议将 JDK 移植到 Linux/RISC-V,这是一种免费的开源 RISC 指令集架构。将支持模板解释器、C1 和 C2 JIT 编译器以及当前所有的主线 GC,包括 ZGC 和 Shenandoah。这个 JEP 的主要重点是将端口集成到 JDK 主线存储库中。
JDK 20
计划于 2023 年 3 月发布 GA 版本,目前没有针对JDK 20的目标 JEP。但是,根据最近提交的 JEP 草案和 JEP 候选者,我们可以推测哪些 JEP 有可能包含在 JDK 20 中。
JEP 429,Extent-Local Variables (Incubator),在 Project Loom 的支持下,提议在线程内和跨线程共享不可变数据。这比线程局部变量更受欢迎,尤其是在使用大量虚拟线程时。有关 JEP 429 的更多详细信息,请参阅此 InfoQ新闻报道。
JEP 草案 8277163,Value Objects (Preview)是由 Project Valhalla 赞助的 JEP 功能,它建议创建值对象 - 指定其实例行为的无身份值类。该草案与 JEP 401, Primitive Classes (Preview)相关,仍处于候选状态。
JEP 401,Primitive Classes (Preview),同样在 Project Valhalla 的支持下,引入了开发人员声明的原始类——在前面提到的值对象(预览)JEP 草案中定义的特殊类型的值类——定义了新的原始类型。
JEP 草案 8273943,字符串模板(预览版),JEP 提议使用字符串模板增强 Java 编程语言的功能,这些模板类似于字符串文字,但包含在运行时合并到字符串模板中的嵌入式表达式。
JEP 草案 8280836,Sequenced Collections,提议引入“一个新的接口系列,表示集合的概念,其元素以明确定义的顺序或顺序排列,作为集合的结构属性。” 这是因为 Collections Framework 中缺乏定义明确的排序和统一的操作集。
JEP 草案 8284289,改进的为 Profiling 异步获取调用跟踪的方法,一种特性 JEP 类型,建议定义一个有效的 API,用于从具有 Java 和本机帧信息的信号处理程序中获取用于分析的异步调用跟踪。
JEP Draft 8283227, JDK Source Structure,一个信息 JEP,描述了 JDK 源代码和 JDK 存储库中相关文件的整体布局和结构。该 JEP 建议帮助开发人员适应 JEP 201,模块化源代码中描述的源代码结构,在 JDK 9 中提供。
JEP 草案 8280389,ClassFile API,提议提供一个用于解析、生成和转换 Java 类文件的 API。该 JEP 最初将作为JDK 中ASM(Java 字节码操作和分析框架)的内部替代品,并计划将其作为公共 API 开放。Oracle 的 Java 语言架构师Brian Goetz将 ASM 描述为“带有大量遗留包袱的旧代码库”,并提供了有关该草案将如何演变并最终取代 ASM 的背景信息。
JEP 草案 8278252,JDK 打包和安装指南,一个信息性 JEP,提议为在 macOS、Linux 和 Windows 上创建 JDK 安装程序提供指南,以减少不同 JDK 提供者在 JDK 安装之间发生冲突的风险。其目的是通过形式化安装目录名称、包名称和其他可能导致冲突的安装程序元素,在安装 JDK 的更新版本时促进更好的体验。
我们预计 Oracle 将很快开始针对 JDK 20 的其中一些 JEP 和其他 JEP。
-
Q1 Project Leyden 状态: https://www.reddit.com/r/java/comments/w0zgw1/comment/ighkpwl
-
Project Leyden: Beginnings: https://mail.openjdk.org/pipermail/leyden-dev/2022-May/000001.html
-
Q2 Project Liliput 状态:https://www.reddit.com/r/java/comments/w0zgw1/comment/igjnvl0
-
Milestone 1 of Project Liliput:https://mail.openjdk.org/pipermail/lilliput-dev/2022-May/000457.html
-
Q3 Project Valhalla 状态:https://www.reddit.com/r/java/comments/w0zgw1/comment/ighp4s9
-
JEP draft: Value Objects (Preview):https://openjdk.org/jeps/8277163
-
JEP 401: Primitive Classes (Preview):https://openjdk.org/jeps/401
-
JEP 402: Classes for the Basic Primitives (Preview):https://openjdk.org/jeps/402
-
JEP draft: Universal Generics (Preview):https://openjdk.org/jeps/8261529
-
Q4 值类型与原始类型模式匹配: https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Q5 值类型与原始类型模式与 record:https://www.reddit.com/r/java/comments/w0zgw1/comment/ignl15f
-
Q6 值类型与原始类型操作符重载:https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Brian Gotez(Java 平台总架构师)对于值类型的解说:https://www.youtube.com/watch?v=jDU-JALUDd0&t=1435s
-
Q7 record 的 wither 复制:https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Functional Transformation of Immutable Objects: https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md
-
Q8 字符串插值:https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
JEP draft: String Templates (Preview):https://openjdk.org/jeps/8273943
-
JavaOne:https://www.oracle.com/cloudworld/javaone/
-
Q9 在字符串模板中使用 {:https://twitter.com/a_boiarshinov/status/1548561533004763137
-
Q10 封闭类 switch 性能优化:https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Q11 结构化 Union 类型:https://www.reddit.com/r/java/comments/w0zgw1/comment/igijtkp 通过引入一个库将在不同线程中运行的多个任务视为单个工作单元来简化多线程编程。这可以简化错误处理和取消,提高可靠性并增强可观察性。
-
Q12 new 省略:https://www.reddit.com/r/java/comments/w0zgw1/comment/igm41mw
-
Q13 新的 web 框架:https://www.reddit.com/r/java/comments/w0zgw1/comment/igjnvl0
-
Q14 兼容 refined 泛型(Java 是泛型擦除):https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Q15 新的前端:https://www.youtube.com/channel/UCmRtPmgnQ04CMUpSUqPfhxQ/community
-
Q16 默认不可变:https://www.reddit.com/r/java/comments/w0zgw1/comment/igio0le
-
Q17 空指针编译时安全性检查:https://www.reddit.com/r/java/comments/w0zgw1/comment/igio0le
-
JSpecify: 通过注解辅助静态代码检查:https://jspecify.dev/
-
Q18 加入 Java:https://inside.java/jobs/
JEP 428:简化 Java 多线程编程的结构化并发
JEP咖啡屋11[熟肉]-虚拟线程这是 Oracle Java developer advocate 之一 José Paumard 主持的一系列节目,主要介绍 JEP(JDK Enhancement Proposal),这是节目的第11期,主要介绍了Java 19 中的预览特性虚拟线程,包括虚拟线程是什么,如何替代传统线程模型,以及如何使用虚拟线程和使用注意事项等等https://mp.weixin.qq.com/s/r_uwOMgwygaJwnfA2F85qAJEP 405: Record Patterns (Preview)https://openjdk.org/jeps/405Data Oriented Programming in Javahttps://www.infoq.com/articles/data-oriented-programming-java
面向数据的编程鼓励我们将数据建模 为 data。记录、密封类和模式匹配共同使这变得更容易。
记录允许我们使用类简单地对数据建模;密封类让我们 选择模型;模式匹配为我们提供了一种对多态数据进行操作的简单且类型安全的方式。