JDK8升级到JDK17的新特性

前言

随着AI时代的浪潮席卷而来,人工智能技术在各行各业的应用愈发广泛,开发领域也迎来了新的变革。为了更好地适配AI场景的开发需求,SpringAI已正式发布,它为开发者提供了构建AI应用的强大工具和框架。而要使用SpringAI,与之配套的Springboot需要升级到3.X版本,这就对JDK的版本提出了新的要求——Springboot3.X明确要求JDK必须在17及以上版本。​

JDK8作为一款经典且被广泛应用的版本,陪伴开发者走过了多年,但JDK17带来了诸多新特性和性能优化,能够更好地支持现代应用开发,尤其是在应对AI相关的复杂计算和高并发场景时表现更为出色。因此,了解JDK8到JDK17的新特性,顺利完成版本升级,对于跟上技术发展步伐、提升开发效率至关重要。

各个特性的说明与代码展示

1、局部变量类型推断(var关键字,JDK10)

在JDK10中引入,允许声明局部变量时省略类型,由编译器自动推断变量类型

    /**
     * 局部变量关键字
     */
    public static void varTest() {
        // JDK 8及之前
        String message = "Hello, World!";
        User userInfo = new User("tom", 18);

        // 升级后
        var a1 = "hello ";
        var a2 = 1L;
        var user = new User("tom", 18);
        user.introduce();
        String name = user.name();
        log.info(name);
        User jerry = User.build("jerry", 20);
        jerry.introduce();
        log.info(jerry.toString());
    }

2、文本块(Text Blocks,JDK13预览,JDK15正式引入)

为多行字符串提供了更便捷的方式,无需再使用换行符和拼接符号,特别适合SQL语句、JSON字符串、HTML代码等多行文本的场景

    /**
     * 文本块
     */
    public static void textTest() {
        String old = "select *\n" +
                "from user\n" +
                "where name = \"tom\" ";
        String newStr = """
                select * 
                from user
                where name = "tom"
                """;
        log.info(old);
        log.info(newStr);
    }

3、密封类(Sealed Classes,JDK15预览,JDK17正式引入)

密封类可以限制哪些类能够继承它,增强了代码的封装性和安全性,避免了不必要的继承和扩展

/**
 * 封闭类是使用sealed修饰的类或接口,它通过permits子句明确列出允许继承或实现它的子类(称为受许可的子类)
 * <p>
 * 限制继承层次,防止未授权的类扩展。
 * 支持模式匹配(如 instanceof、switch)的完整性检查。
 * 子类必须使用final、sealed、non-sealed修饰符之一
 *
 * @author stone
 * @date 2025/7/7 16:45
 */
public sealed class Person permits PersonMan, PersonWoman, PersonUnknown {
}


/**
 * @author stone
 * @date 2025/7/7 16:45
 */
public final class PersonMan extends Person {
}


/**
 * @author stone
 * @date 2025/7/7 16:48
 */
public non-sealed class PersonUnknown extends Person {
}


/**
 * @author stone
 * @date 2025/7/7 16:45
 */
public final class PersonWoman extends Person{
}


配合instanceOfyu语法

    /**
     * 密封类
     */
    public static void sealedTest() {
        Person tom = new PersonMan();
        if (tom instanceof PersonMan man) {
            log.info(man.toString());
        }
    }

4、instanceof模式匹配(JDK16正式引入)

允许在判断的同时进行类型转换,不必再强制类型转换

        // 模式匹配: 可以直接使用变量,不需要显式的类型转换
        Object object = "111";
        if (object instanceof String str) {
            log.info(str);
        }

5、增强的switch表达式(JDK12预览,JDK14正式引入)​

可以使用箭头语法,增加yield关键字

    public static String switchTest(String day) {
        // jdk12: 引入->操作符、不需要break语句来防止穿透
        String typeOfDay = switch (day) {
            case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
            case "SATURDAY", "SUNDAY" -> "Weekend";
            default -> "Unknown";
        };
        log.info(typeOfDay);

        // jdk13: 使用yield在Switch表达式中直接返回
        return switch (day) {
            case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Weekday";
            case "SATURDAY", "SUNDAY" -> "Weekend";
            default -> {
                if (day.isEmpty()) {
                    yield "day is empty";
                } else {
                    yield "Unknown";
                }
            }
        };
    }

6、记录类(Records,JDK16正式引入)

记录类是一种用于存储数据的简洁类,减少了样板代码的编写

/**
 * 适用于存储数据而没有复杂业务逻辑的情况
 * <p>
 * 自动生成构造器、equals()、hashCode() 和 toString() 方法,以及每个字段的 getter方法
 * 记录中,所有字段都必须在记录的参数列表中定义。
 * 记录是不可变的,默认是final的:字段一旦赋值,不能被修改。
 * 无法在记录内部定义额外的 private final字段,可以定义对应的static字段
 *
 * @author stone
 * @date 2025/7/4 16:15
 */
public record User(String name, Integer age) {

    public static final String className = "101班";

    public void introduce() {
        System.out.println(className + "=" + name + "=" + age);
    }

    public static User build(String name, Integer age) {
        return new User(name, age);
    }

}

7、空指针异常增强(JDK14)​

对空指针异常信息进行了优化,能够更精确地指出引发空指针异常的位置和原因

    public static void main(String[] args) throws Exception {
        var user = new User("tom", 18);
        System.out.println(user.name());
        user = null;
        System.out.println(user.name());
    }



Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.stone.tool.jdk17.User.name()" because "user" is null
	at com.stone.tool.jdk17.Jdk17Demo.main(Jdk17Demo.java:34)

8、Http客户端

引入新的Http Client Api,支持链式调用,同时内置了请求构建、响应处理、超时控制等功能。

涵盖GET/POST/PUT/DELETE等HTTP方法,支持表单提交、文件上传、WebSocket通信等场景

    /**
     * http客户端
     */
    public static void httpTest() throws IOException, InterruptedException {
        HttpClient client = HttpClient.newBuilder()
                .version(HttpClient.Version.HTTP_2) // 指定 HTTP 版本
                .followRedirects(HttpClient.Redirect.NORMAL) // 自动处理重定向
                .connectTimeout(Duration.ofSeconds(10)) // 连接超时设置
                .build();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.baidu.com/"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString("{\"key\":\"value\"}")) // 请求体
                .build();

        // 同步请求,阻塞线程
        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        log.info("Status code: " + response.statusCode());
        log.info("Response body: " + response.body());

        System.out.println("===============================================");

        // 异步执行,不阻塞线程
        client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body) // 处理响应体
                .thenAccept(body -> log.info("Response: " + body)) // 消费结果
                .exceptionally(ex -> {
                    log.error("Exception occured!", ex);
                    return null;
                });


        // 批量请求
//        List<HttpRequest> requests = Arrays.asList(request1, request2, request3);
//        CompletableFuture.allOf(
//                requests.stream()
//                        .map(req -> client.sendAsync(req, HttpResponse.BodyHandlers.ofString()))
//                        .toArray(CompletableFuture[]::new)
//        ).thenRun(() -> System.out.println("All requests completed"));


        // 字符串请求体
        HttpRequest.BodyPublishers.ofString("Hello, World!");
        // 文件请求体
        HttpRequest.BodyPublishers.ofFile(Path.of("data.json"));
        // 字节数组请求体
        HttpRequest.BodyPublishers.ofByteArray(new byte[]{1, 2, 3});
        // 空请求体(用于 GET 请求)
        HttpRequest.BodyPublishers.noBody();

        // 处理为字符串
        HttpResponse.BodyHandlers.ofString();
        // 保存到文件
        HttpResponse.BodyHandlers.ofFile(Path.of("response.txt"));
        // 处理为字节数组
        HttpResponse.BodyHandlers.ofByteArray();
        // 忽略响应体
        HttpResponse.BodyHandlers.discarding();
        // 流式处理大响应
        HttpResponse.BodyHandlers.ofInputStream();


        log.info("method end line...");
    }
    /**
     * http WebSocket客户端
     */
    public static void httpWebSocketTest() throws IOException, InterruptedException {
        WebSocket.Listener listener = new WebSocket.Listener() {
            @Override
            public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
                System.out.println("Received: " + data);
                return new CompletableFuture<>();
            }
        };
        WebSocket webSocket = HttpClient.newBuilder()
                .build()
                .newWebSocketBuilder()
                .buildAsync(URI.create("ws://echo.websocket.org"), listener)
                .join(); // 阻塞等待连接建立

        // 发送消息
        webSocket.sendText("Hello, WebSocket!", true);
        webSocket.abort();
    }

9、GC垃圾回收

新增垃圾回收器

  • ZGC(Z Garbage Collector,JDK11引入,JDK15正式转正):ZGC是一款低延迟垃圾收集器,设计目标是支持TB级内存、GC停顿时间控制在毫秒级以内,非常适合大内存、高并发的应用(如AI模型训练、大规模数据处理)
  • Shenandoah(JDK12引入,JDK17成为正式特性):Shenandoah是另一款注重低延迟的垃圾收集器,由Red Hat主导开发,与ZGC目标类似,减少停顿时间,更适合大型业务系统

代码地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值