JDK17新增特性

本文主要介绍一些在JDK17中新增的一些语法特性。

目录

前言

一、yield关键字

二、var关键字

三、空指针异常

四、密封类

五、接口中的私有方法

六、instanceof

七、其他

总结


前言

从SpringBoot3.0开始,已经不再支持JDK8了,从3.0开始,转变为了JDK17。参考资料,来自官方博客:https://spring.io/blog/2022/01/20/spring-boot-3-0-0-m1-is-now-available?spm=a2c6h.12873639.article-detail.24.766d46b40LM1IV

官方的维护版本都是SpringBoot3.x的了,但是之前的版本也是可以用的,只是官方不再进行版本更新了。

总的来说,选用Java 17,概括起来有三个主要原因:JDK17是LTS,也就是长期支持版,可以免费商用到2029年,而且将前面几个过渡版去其糟粕取其精华;JDK 17的性能提升不少,比如重写了底层NIO,至少提升了10%起步;大多数第三方框架和库都已经支持,不会有什么大坑。


一、yield关键字

我们在正常去使用switch-case结构的时候是这样操作的:

java 复制代码
public class Main {
    public static void main(String[] args) {
        String data = "one";
        int result;
        switch(data) {
            case "one":
                result =  1;
                break;
            case "two":
                result =  2;
                break;
            default:
                result =  -1;
                break;
        }
        System.out.println(result);
    }
}

我们可以用如下的语法形式来简化switch结构:

java 复制代码
public class Main {
    public static void main(String[] args) {
        String data = "one" ;
        int result = switch (data) {
            case "one"->1;
            case "two"->2;
            default->-1;
        };
        System.out.println(result) ;
    }
}

在Java13开始,我们引入了yield关键字,它也可以用于从case的代码块中返回值,它主要就是替换了我们上面这种形势之中出现的->运算符。比如如下的代码形式:

java 复制代码
public class Main {
    public static void main(String[] args) {
        String data = "one" ;
        int result = switch (data) {
            case "one" : yield 1;
            case "two": yield 2;
            default : yield -1;
        };
        System.out.println(result) ;
    }
}

无论上述哪种形式,我们都会得到如下的结果:

二、var关键字

从Java 10开始,我们引入了var关键字,比如如下的代码:

java 复制代码
var name = "zhangsan";
var age = 10;

上述代码中,编译器会自动推断出name是⼀个String类型,age是⼀个int类型。那么我们为什么要使用var?一个主要的原因就是使用var可以使代码更简洁。有时候,类型名称可能会非常长,例如泛型。var就像是⼀个简化器,让我们不必反复写出繁琐的类型名。比如说下面这样:

java 复制代码
public static void main(String[] args) {

Map<String, List<Map<Integer, String>>> complexMap = new HashMap<String,
List<Map<Integer, String>>>();

var complexMap2 = new HashMap<String, List<Map<Integer, String>>>();
}

但在使用var的时候,我们要注意如下的问题,不能使用var来声明字段,不能使用var来声明方法参数,不能使用var来声明方法返回类型,var声明变量必须初始化,但是不能初始化为null。也就是如下的情况都是对于var的错误使用:

java 复制代码
class OrgCat {

    public var name;//error

    public var eat(var str) {//error

    }

}

public static void main(String[] args) {

    var complexMap2 = 10;

    System.out.println(complexMap2);

    var str = null;//error

}

三、空指针异常

出现异常的具体方法和原因都⼀目了然。如果你的⼀行代码中有多个方法、多个变量,可以快速定位问题所在,如果是JDK1.8,有些情况下真的不太容易看出来。比如JDK8,就是下面这种报错:

而JDK17的话,就是下面这种:

四、密封类

密封类⼀般应用在类和接口中,对接口和类的实现和继承进行约束。主要使用的关键字是final。当

这个类被final修饰了,被修饰的类就变成完全封闭的状态了,所有类都没办法继承。JDK17提供了⼀个新的关键字sealed,密封类除了可以被该关键字修饰,并且在声明末尾用permits表示要开放给哪些类型。下面这段代码Animal为密封类,然后使用permits关键字,把继承权限开放给了Dog 类:

java 复制代码
sealed class Animal permits Dog{
    public String name;
    public int age;

    public void eat() {
        System.out.println("eat()....");
    }
}

non-sealed class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println(this.name+ "正在吃狗粮....");
    }
}

总的来说,其有如下需要注意的部分。首先是sealed修饰的类必须要有子类,否则就会报错,比如下面的代码,就会提示我们Sealed class must have subclasses的信息:

java 复制代码
sealed class Animal {
    public String name;
    public int age;
    public void eat() {
        System.out.println("eat()....");
    }
}

sealed class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println(this.name+ "正在吃狗粮....");
    }
}

其次我们如果使用non-sealed关键字来修是的话就表示不限制,任何类都可以来继承,比如最开始的代码。然后如果我们的类型未被permits关键字允许,则我们就没办法去继承:

java 复制代码
sealed class Animal permits Dog {
    public String name;
    public int age;
    public void eat() {
        System.out.println("eat()....");
    }
}
non-sealed class PetDog extends Animal {

}

上面的代码可以更改为如下部分:

java 复制代码
sealed class Animal permits Dog,PetDog {
    public String name;
    public int age;
    public void eat() {
        System.out.println("eat()....");
    }
}
non-sealed class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println(this.name+ "正在吃狗粮....");
    }
}
non-sealed class PetDog extends Animal {

}

五、接口中的私有方法

Java 8中接口可以有默认方法。Java 9之后,可以在接口内实现私有方法实现。比如下面的代码:

java 复制代码
interface HelloService {
    public void sayHello();
    // 默认⽅法
    default void saySomething(){
        syaEngHello();
        sayHello();
    };
    // 私有⽅法
    private void syaEngHello(){
        System.out.println("Hello!");
    }
}

六、instanceof

我们之前使用instanceof关键字进行过如下的操作:

java 复制代码
if (obj instanceof String) {
    String str = (String) obj;
    ...
}

上面的instancof语法⼀共做了三件事,判断是否为String类型;如果是,转成String类型;创建⼀个名为str 的临时变量。在JDK16中,使用模式匹配思想改进了instanceof用法,可以做到以下优化效果:

java 复制代码
if (obj instanceof String str) {// obj是否为String类型,如果是创建临时变量str
}

七、其他

其他还有很多未列举到的,比如下面这些:

  1. ZGC-新⼀代垃圾回收器、G1垃圾回收器相关等等

  2. record 类的使用

  3. Stream API的部分改进

  4. HttpClient 重写了,支持 HTTP2.0

  5. 支持 List.of()、Set.of()、Map.of()和Map.ofEntries()等工厂方法实例化对象

等等等等很多的知识,之后遇到我们再行介绍。


总结

本文介绍了JDK17中的主要新特性:switch表达式支持yield返回值,简化了switch-case结构;var关键字支持局部变量类型推断,提升代码简洁性;改进了空指针异常提示,使问题定位更清晰;新增sealed密封类,通过permits精确控制继承权限;接口支持私有方法实现;instanceof模式匹配简化类型判断和转换。这些改进使Java代码更简洁、安全,同时提升了开发效率和性能。JDK17作为长期支持版本,是企业级应用的理想选择。

相关推荐
阿里加多6 小时前
第 4 章:Go 线程模型——GMP 深度解析
java·开发语言·后端·golang
likerhood6 小时前
java中`==`和`.equals()`区别
java·开发语言·python
小小李程序员6 小时前
Langchain4j工具调用获取不到ThreadLocal
java·后端·ai
zs宝来了7 小时前
AQS详解
java·开发语言·jvm
telllong7 小时前
Python异步编程从入门到不懵:asyncio实战踩坑7连发
开发语言·python
wjs20249 小时前
JavaScript 条件语句
开发语言
lulu12165440789 小时前
Claude Code Harness架构技术深度解析:生产级AI Agent工程化实践
java·人工智能·python·ai编程
阿里加多9 小时前
第 1 章:Go 并发编程概述
java·开发语言·数据库·spring·golang