官方地址
JDK8,JDK11,JDK17,JDK21是长期维护的版本。spring boot3最低支持JDK17。
1、语言新特性
1.1接口新增默认方法与静态方法:
Interface Default Method:For creating a default method in java interface, we need to use “default” keyword with the method signature.
Interface Static Method:interface static method is similar to default method except that we can’t override them in the implementation classes.
1.2 Functional Interfaces函数式接口
含有一个显式声明函数(抽象方法)的接口称为函数接口,注释@FunctionalInterface用作检查代码块,包package java.util.function,通常使用lambda expressions来实体化函数接口。
函数式接口:函数形接口 、供给形接口、消费型接口、判断型接口。
1.2 Lambda表达式
语法:( object str,…)[参数列表] ->[箭头符号] 代码块或表达式。
特性:Lambda 的类型是从使用 Lambda 的上下文推断出来的。上下文中 Lambda 表达式需要的类型称为目标类型(一个 Lambda表达式所在的类的类型。并且必须存在一个目标类型); 匿名、函数、传递、简洁。
Arrays.sort(new SysUser[5], (SysUser a, SysUser b) -> {
return a.getUserId().compareTo(b.getUserId());
});
1.3 方法引用
方法引用操作符“::”,左边是类名或者某个对象的引用,右边是方法名,有下面几种方式:
(1)对象(引用)::实例方法名 new SysUser()::getUserName
(2)类名::静态方法名 Function<Long, Long> f = Math::abs;
(3)类名::实例方法名 SysUser::getUserName
(4)类名::new SysUser::new
(5)类型[]::new Function<Integer, SysUser[]> funUsers = SysUser[]::new;
1.4 重复注解@Repeatable
重复注解机制,相同的注解可在同一地方声明多次.
@Repeatable(Annotations.class)
public @interface MyAnnotation {
String role();
}
public @interface Annotations {
MyAnnotation[] value();
}
public class RepeatAnnotationUseOldVersion {
@MyAnnotation(role="Admin")
@MyAnnotation(role="Manager")
public void doSomeThing(){
}
}
对比以前jdk8的注解实现:
public @interface MyAnnotation {
String role();
}
public @interface Annotations {
MyAnnotation[] value();
}
public class RepeatAnnotationUseOldVersion {
@Annotations({@MyAnnotation(role="Admin"),@MyAnnotation(role="Manager")})
public void doSomeThing(){
}
}
1.5 类库新特性
●java.util.stream类库包新特性 stream
●java.util.Optional 类新特性
●java.util.Base64 类新特性
●Java.time 类新特性
●其它常用类新增特性
●HashMap类性能提升
java.util.stream 类库包新特性
Stream流的特性
定 义:支持数据处理操作的源生成的元素序列。它并非是数据结构,也不是容器,而是一个过程。
流类型:tream 串行流、parallelStream 并行流
Stream 的源数据来于 Collection、Arrays 等类型,因为它的方法参数都是函数式接口类型,所以通常和 Lambda 表达式一起使用。
Stream 不存储数据,也不改变源数据,但它提供了对集合数据进行检索和逻辑处理的功能,包括筛选、排序、统计、计数等。
Optional
主要用来处理传入的数据的空指针NullPointerException问题。
Optional.ofNullable(person)
.map(p -> p.getUserName())
.map(h -> h.getUserId())
.ifPresent(userId->System.out.println(userId));
JDK 17 是一个长期维护的版本(LTS)。Java 17 提供了数千个性能、稳定性和安全性更新,以及 14 个 JEP(JDK 增强提案),进一步改进了 Java 语言和平台,以帮助开发人员提高工作效率。JDK 17 包括新的语言增强、库更新、对新 Apple (Mx CPU)计算机的支持、旧功能的删除和弃用,并努力确保今天编写的 Java 代码在未来的 JDK 版本中继续工作而不会发生变化。
JDK21共有15个新特性,较为重要新特性:
String Templates(字符串模板)
String Templates 提供了一种更简洁、更直观的方式来动态构建字符串。通过使用占位符${},我们可以将变量的值直接嵌入到字符串中,而不需要手动处理。
目前支持三种模板处理器:
String name = "Lokesh";
//STR
String message = STR."Greetings \{name}.";
//FMT
String message = STR."Greetings %-12s\{name}.";
//RAW
StringTemplate st = RAW."Greetings \{name}.";
String message = STR.process(st);
Sequenced Collections(序列化集合)
Sequenced Collections(序列化集合,也叫有序集合),这是一种具有确定出现顺序(encounter order)的集合(无论我们遍历这样的集合多少次,元素的出现顺序始终是固定的)。序列化集合提供了处理集合的第一个和最后一个元素以及反向视图(与原始集合相反的顺序)的简单方法。
Sequenced Collections 包括以下三个接口:
SequencedCollection 接口:继承了 Collection接口, 提供了在集合两端访问、添加或删除元素以及获取集合的反向视图的方法。
interface SequencedCollection<E> extends Collection<E> {
// New Method
SequencedCollection<E> reversed();
// Promoted methods from Deque<E>
void addFirst(E);
void addLast(E);
E getFirst();
E getLast();
E removeFirst();
E removeLast();
}
SequencedSet接口:继承了 SequencedCollection 接口并重写了 reversed() 方法。
SequencedMap 接口:继承了 Map接口, 提供了在集合两端访问、添加或删除键值对、获取包含 key 的 SequencedSet、包含 value 的 SequencedCollection、包含 entry(键值对) 的 SequencedSet以及获取集合的反向视图的方法。
interface SequencedMap<K,V> extends Map<K,V> {
// New Methods
SequencedMap<K,V> reversed();
SequencedSet<K> sequencedKeySet();
SequencedCollection<V> sequencedValues();
SequencedSet<Entry<K,V>> sequencedEntrySet();
V putFirst(K, V);
V putLast(K, V);
// Promoted Methods from NavigableMap<K, V>
Entry<K, V> firstEntry();
Entry<K, V> lastEntry();
Entry<K, V> pollFirstEntry();
Entry<K, V> pollLastEntry();
}
Generational ZGC(分代 ZGC)
分代 ZGC 可以显著减少垃圾回收过程中的停顿时间,并提高应用程序的响应性能。这对于大型 Java 应用程序和高并发场景下的性能优化非常有价值。 ZGenerational 设为默认值,即默认打开 ZGC 的分代 GC。
Pattern Matching for switch(switch 的模式匹配)
增强 Java 中的 switch 表达式和语句,允许在 case 标签中使用模式。当模式匹配时,执行 case 标签对应的代码。
如下代码switch 表达式使用类型模式来进行匹配:
static 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();
};
}
Foreign Function & Memory API(外部函数和内存 API)
外部函数和内存 API 在 Java 17 中进行了第一轮孵化,由 JEP 412open in new window 提出。Java 18 中进行了第二次孵化,由JEP 419open in new window 提出。Java 19 中是第一次预览,由 JEP 424open in new window 提出。JDK 20 中是第二次预览,由 JEP 434open in new window 提出。JDK 21 中是第三次预览,由 JEP 442open in new window 提出。
Java 程序可以通过该 API 与 Java 运行时之外的代码和数据进行互操作。通过高效地调用外部函数(即 JVM 之外的代码)和安全地访问外部内存(即不受 JVM 管理的内存),该 API 使 Java 程序能够调用本机库并处理本机数据,而不会像 JNI 那样危险和脆弱。
Foreign Function & Memory API (FFM API) 定义了类和接口:
Virtual Threads(虚拟线程)
虚拟线程在 Java 19 中进行了第一次预览,由JEP 425提出。JDK 20 中是第二次预览。最终,虚拟线程在 JDK21 顺利转正。
虚拟线程(Virtual Thread-)是 JDK 而不是 OS 实现的轻量级线程(Lightweight Process,LWP),许多虚拟线程共享同一个操作系统线程,虚拟线程的数量可以远大于操作系统线程的数量。
虚拟线程避免了上下文切换的额外耗费,兼顾了多线程的优点,简化了高并发程序的复杂,可以有效减少编写、维护和观察高吞吐量并发应用程序的工作量。
在引入虚拟线程之前,java.lang.Thread 包已经支持所谓的平台线程,也就是没有虚拟线程之前,我们一直使用的线程。JVM 调度程序通过平台线程(载体线程)来管理虚拟线程,一个平台线程可以在不同的时间执行不同的虚拟线程(多个虚拟线程挂载在一个平台线程上),当虚拟线程被阻塞或等待时,平台线程可以切换到执行另一个虚拟线程。虚拟线程、平台线程和系统内核线程的关系图如下所示:
四种创建虚拟线程的方法:
// 1、通过 Thread.ofVirtual() 创建
public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
// 创建不启动
Thread unStarted = Thread.ofVirtual().unstarted(customThread);
unStarted.start();
// 创建直接启动
Thread.ofVirtual().start(customThread);
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
// 2、通过 Thread.startVirtualThread() 、创建
public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
Thread.startVirtualThread(customThread);
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
// 3、通过 Executors.newVirtualThreadPerTaskExecutor() 创建
public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
executor.submit(customThread);
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}
//4、通过 ThreadFactory 创建
public class VirtualThreadTest {
public static void main(String[] args) {
CustomThread customThread = new CustomThread();
ThreadFactory factory = Thread.ofVirtual().factory();
Thread thread = factory.newThread(customThread);
thread.start();
}
}
static class CustomThread implements Runnable {
@Override
public void run() {
System.out.println("CustomThread run");
}
}