Java部分新特性

模式匹配

instance of 模式匹配

之前写法

java 复制代码
public void print(Object o) {
    if (o instanceof String){
        String str = (String) obj;
        System.out.println("This is a String of length " + s.length());
    } else {
        System.out.println("This is not a String");
    }
}

java 14之后引入了新的模式匹配特性,允许在instanceof检查之后直接进行类型转换,而不需要显式地进行类型转换。

java 复制代码
public void print(Object o) {
    if (o instanceof String s){
        System.out.println("This is a String of length " + s.length());
    } else {
        System.out.println("This is not a String");
    }
}

Switch模式匹配

Switch 的模式匹配是 JDK 21 的最终功能。它在 Java SE 17、18、19 和 20 中作为预览功能推出。

java 复制代码
Object o = ...; // any object
String formatter = switch(o) {
    case Integer i -> String.format("int %d", i);
    case Long l    -> String.format("long %d", l);
    case Double d  -> String.format("double %f", d);
    default        -> String.format("Object %s", o.toString());
};

switch 的模式匹配不仅能提高代码的可读性,还能提高代码的性能。if-else-if 语句的求值与该语句的分支数成正比;分支数加倍会使求值时间加倍。switch 的求值与 case 数无关。 if 语句的时间复杂度为O(n),而 switch 语句的时间复杂度为O(1)。

Record

record是一种特殊的不可变类型,java16 成为正式特性

java 复制代码
public record Point(int x, int y) {}
  • record 中的字段是隐式 final,一旦创建实例后,其字段值无法更改
  • Java 会自动为 record 类生成 equals()、hashCode()、toString() 和构造函数等常用方法。
  • record还可以定义方法和自定义构造函数。
java 复制代码
public record State(String name, String capitalCity, List<String> cities) {

    public State {
        // List.copyOf returns an unmodifiable copy,
        // so the list assigned to `cities` can't change anymore
        cities = List.copyOf(cities);
    }

    public State(String name, String capitalCity) {
        this(name, capitalCity, List.of());
    }

    public State(String name, String capitalCity, String... cities) {
        this(name, capitalCity, List.of(cities));
    }

}
  • record不支持继承,但可以实现接口
java 复制代码
public record Person(String name, int age) implements Greetable {
    @Override
    public String greet() {
        return "Hello, " + name;
    }
}

interface Greetable {
    String greet();
}

适用于表示只包含数据的对象,例如 DTO(数据传输对象)、VO(值对象)等,在需要确保不可变数据的情况下非常有用。

Record Pattern

Java 的 Record Pattern 是从 Java 16 引入,Java 21作为正式特性的一种模式匹配特性,用于简化对 record 类型的解构和模式匹配操作。

通过模式直接访问 record 的字段,而不需要显式调用 getter 方法。与 switch 和 instanceof 结合:可以在 switch 表达式或 if 语句中对 record 进行模式匹配。

java 复制代码
Object o = ...; // any object
if (o instanceof Point(int x, int y)) {
    // do something with x and y
}

虚拟线程

Java 19引入了虚拟线程,并且在Java 21成为正式特性。

虚拟线程对并发任务数量很大且任务大多在网络 I/O 上阻塞时很有用,但对CPU密集型任务没有任何好处。

虚拟线程特点

  • 在同一个线程组中:所有虚拟线程都被组织在一个线程组中,这意味着它们可以被统一管理和监控。
  • 优先级为 NORM_PRIORITY:虚拟线程的默认优先级为正常优先级。
  • 是守护线程:所有虚拟线程都是守护线程。

平台线程与虚拟线程

只有当虚拟线程执行实际工作时,才会将其分配给平台线程(载体线程)

Parameter 平台线程 虚拟线程
堆栈大小 1 MB 动态调整
启动时间 > 1000 µs 1-10 µs
上下文切换时间 1-10 µs ~ 0.2 µs
可允许线程数 < 5000 百万

虚拟线程的栈存储在堆中,作为栈块对象(stack chunk objects),使虚拟线程能够动态管理内存,避免固定大小的栈带来的内存浪费。当虚拟线程需要更多的栈空间(比如进入更深的函数调用时),它的栈会增长。相反,当不再需要那么多栈空间时,栈可以缩小。而平台线程的栈是直接由操作系统分配,与每个线程相关的栈空间通常是存储在操作系统的内存中。

如何正确使用虚拟线程

  • 不要使用虚拟线程执行CPU密集型任务
  • 在每个请求线程模型中编写阻塞同步代码
  • 不要使用虚拟线程池
  • 使用信号量(semaphores)而不是固定线程池来限制并发
  • 谨慎使用threadLocal或使用ScopedValue代替(ScopedValue 是一个泛型类,允许在当前线程(或虚拟线程)及其子线程中共享一个值。它是一种轻量级的方式来管理线程的上下文信息,无需使用传统的线程局部变量)
  • 谨慎使用synchronized,可使用reentrant locks代替。synchronized由于其监视器锁的实现机制,一旦线程获取了锁,就会固定在平台线程上,直到锁被释放 。 相比之下,ReentrantLock提供了更灵活的锁定机制,允许虚拟线程在遇到阻塞操作时从其承载的平台线程上卸载,让出平台线程给其他虚拟线程使用。
java 复制代码
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

public class JavaDemoApplication {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService service = Executors.newVirtualThreadPerTaskExecutor();
        List<Callable<String>> callables = new ArrayList<>();
        final int ADJECTIVES = 4;
        for (int i = 1; i <= ADJECTIVES; i++)
            callables.add(() -> get("https://horstmann.com/random/adjective"));
        callables.add(() -> get("https://horstmann.com/random/noun"));
        List<String> results = new ArrayList<>();
        for (Future<String> f : service.invokeAll(callables))
            results.add(f.get());
        System.out.println(String.join(" ", results));
        service.close();
    }

    private static final HttpClient client = HttpClient.newHttpClient();


    public static String get(String url) {
        try {
            var request = HttpRequest.newBuilder().uri(new URI(url)).GET().build();
            return client.send(request, HttpResponse.BodyHandlers.ofString()).body();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}

文本块

Java 文本块(Text Blocks)是在Java 13 引入,在Java 15被作为正式特性,用于更方便地处理多行字符串。文本块通过三引号 (""") 语法来定义,可以用来表示跨多行的字符串,从而解决了传统多行字符串拼接时的许多麻烦。文本块使得字符串的定义更加简洁、可读和易于维护,特别是在处理包含换行符、缩进或多行文本时。

java 复制代码
// ORIGINAL
String message = "'The time has come,' the Walrus said,\n" +
                 "'To talk of many things:\n" +
                 "Of shoes -- and ships -- and sealing-wax --\n" +
                 "Of cabbages -- and kings --\n" +
                 "And why the sea is boiling hot --\n" +
                 "And whether pigs have wings.'\n";
                 
     
// BETTER
String message = """
    'The time has come,' the Walrus said,
    'To talk of many things:
    Of shoes -- and ships -- and sealing-wax --
    Of cabbages -- and kings --
    And why the sea is boiling hot --
    And whether pigs have wings.'
    """;

Compactor Strings

在 JDK 9 中,java.lang.String、StringBuilder 和 StringBuffer 类的内部字符存储已从 UTF-16 char数组更改为byte数组加上一个字节的编码标志字段。新的存储表示根据字符串的内容将字符存储/编码为 ISO-8859-1/Latin-1(每个字符一个字节)或 UTF-16(每个字符两个字节)。新添加的编码标志字段指示使用哪种编码。如果 String 对象仅包含单字节/latin-1 字符,则此功能将 String 对象存储字符所需的空间量减少了 50%。

来源

https://dev.java/

https://www.oracle.com/java/

相关推荐
Matlab程序猿小助手4 分钟前
【MATLAB源码-第228期】基于matlab的鼠群优化算法(RSO)无人机三维路径规划,输出做短路径图和适应度曲线.
开发语言·算法·matlab·机器人·无人机
eternal19956 分钟前
优化问题|生产车间布局优化问题及遗传算法求解(MATLAB)
开发语言·matlab
旧日之血_Hayter7 分钟前
docker里的jenkins迁移
java·docker·jenkins
studyer_domi8 分钟前
matlab模糊fis文件制作
开发语言·matlab
z千鑫30 分钟前
【C/C++】深入解析 Stack 与 Queue 数据结构(详解):实现原理、应用场景与性能优化
c语言·开发语言·数据结构·c++·深度学习·算法·排序算法
Duck Bro36 分钟前
MySQL:表的增删改查(CRUD)
android·java·数据库·c++·mysql
BAGAE2 小时前
tomcat,appche,nginix,jboss区别
java·linux·数据库·ubuntu·tomcat
GGBondlctrl2 小时前
【Spring MVC】如何获取cookie/session以及响应@RestController的理解,Header的设置
java·spring·mvc·cookie·session·header·restcontroller
大梦百万秋2 小时前
Spring Boot开发实战:从入门到构建高效应用
java·spring boot
数懒女士2 小时前
Java常见的锁策略
java·算法