JDK17的新特性写法

2023-11-19 09:26:57 浏览数 (2)

JDK17的新特性写法

一、介绍

JDK 17 是 Java Development Kit(Java 开发工具包)的一个版本,是 Oracle 公司提供的 Java SE(Java 平台,标准版)的一部分。以下是 JDK 17 的一些基本信息:

  1. 版本号:JDK 17 的完整版本号是 17,它是 Java SE 17 的版本。
  2. 发布日期:JDK 17 v17.0.0 在 2021 年 9 月 14 日正式发布。
  3. LTS 版本:JDK 17 被标记为 “LTS”(长期支持)版本。LTS 版本提供长期支持和维护,适合用于生产环境。
  4. 特性更新:JDK 17 引入了一些新的特性、改进和增强,包括但不限于密封类、基础类型的模式匹配、日期时间API的升级等。
  5. 垃圾回收器:JDK 17 包含了多种垃圾回收器,包括 ZGC、G1GC、ParallelGC 等,以满足不同场景下的需求。

二、新特性

1)switch

可以不用再写break了,可以进行简化

代码语言:javascript复制
package com.banmoon.switches;

import cn.hutool.core.util.StrUtil;

public class OldSwitchMain {

    public static void main(String[] args) {
        String name = "半月无霜";
        int age;
        switch (name) {
            case "半月无霜":
                age = 18;
                break;
            case "cc":
                age = 66;
                break;
            case "溪月":
                System.out.println("溪月20岁");
                age = 20;
                break;
            case "九月":
            case "八月":
                age = 22;
                break;
            default:
                age = 0;
                break;
        }
        System.out.println(StrUtil.format("姓名:{},年龄:{}", name, age));
    }

}

新写法

代码语言:javascript复制
package com.banmoon.switches;

import cn.hutool.core.util.StrUtil;

public class NewSwitchMain {

    public static void main(String[] args) {
        String name = "半月无霜";
        int age = switch (name) {
            case "半月无霜" -> 18;
            case "cc" -> 66;
            case "溪月" -> {
                System.out.println("溪月20岁");
                yield 20;
            }
            case "九月", "八月" -> 22;
            default -> 0;
        };
        System.out.println(StrUtil.format("姓名:{},年龄:{}", name, age));
    }
}

可以对比一下它们之间的代码差距


除了上面这种增强外,switch关键字还支持了对类的类型进行判断,比如

代码语言:javascript复制
package com.banmoon.switches;

import cn.hutool.core.date.DateUtil;

import java.util.Date;

public class ClassSwitchMain {

    public static void main(String[] args) {
        Object o1 = "123";
        Object o2 = new Date();
        System.out.println(switchMethod(o1));
        System.out.println(switchMethod(o2));
    }

    private static String switchMethod(Object o) {
        return switch (o) {
            case String str -> "字符串类型:"   str;
            case Number number -> "数字类型:"   number;
            case Date date -> "日期类型:"   DateUtil.formatDateTime(date);
            default -> "其他类型";
        };
    }
}

2)字符串三引号

如果在代码中编写sql,或者有换行的长文本的时候,往往充斥着各种n,十分影响阅读,如同下面这样

代码语言:javascript复制
package com.banmoon.stringQuotationMark;

public class OldMain {

    public static void main(String[] args) {
        String sql = "selectn"  
                "    id,n"  
                "    username,n"  
                "    passwordn"  
                "from sys_usern"  
                "where n"  
                "    username = '%s'";
        System.out.printf(sql, "半月无霜");
    }
}

但现在可以通过"""...""",三个引号就可以得到解决,看着十分的清爽。

代码语言:javascript复制
package com.banmoon.stringQuotationMark;

public class NewMain {

    public static void main(String[] args) {
        String sql = """
                select
                    id,
                    username,
                    password
                from sys_user
                where
                    username = '%s'
                """;
        System.out.printf(sql, "半月无霜");
    }

}

话说,这"""的设计是不是借鉴了python呢?越来越好了

3)instanceof增强

在以前我们使用instanceof关键字后,还需要带一个强转,例如下面的这段代码

代码语言:javascript复制
package com.banmoon.instanceofEnhance;

public class OldInstanceofMain {

    public static void main(String[] args) {
        Object o1 = "1";
        Object o2 = 1;
        instanceOf(o1);
        instanceOf(o2);
    }

    private static void instanceOf(Object o) {
        if (o instanceof Integer) {
            Integer i = (Integer) o;
            System.out.println("数字:"   i);
        } else if (o instanceof String) {
            String str = (String) o;
            System.out.println("字符串:"   str);
        } else {
            System.out.println("其他类型");
        }
    }

}

而新写法也比较简单,可以这样写,如果匹配直接就转换了

代码语言:javascript复制
package com.banmoon.instanceofEnhance;

public class NewInstanceofMain {

    public static void main(String[] args) {
        Object o1 = "1";
        Object o2 = 1;
        instanceOf(o1);
        instanceOf(o2);
    }

    private static void instanceOf(Object o) {
        if (o instanceof Integer i) {
            System.out.println("数字:"   i);
        } else if (o instanceof String str) {
            System.out.println("字符串:"   str);
        } else {
            System.out.println("其他类型");
        }
    }

}

4)密封类(Sealec Classes)

提供了一个新的关键字sealec,它的作用修饰父类、接口,变成一个密封类

同时还提供了一个permits,指定与父类接口同包的类才能继承或者实现

如下演示

首先,我们有一个父类

代码语言:javascript复制
package com.banmoon.sealecClasses;

public sealed class Person permits Teacher, Student {
}

这个父类有两个直接子类,StudentTeacher

代码语言:javascript复制
package com.banmoon.sealecClasses;

public final class Student extends Person {
}
代码语言:javascript复制
package com.banmoon.sealecClasses;

public sealed class Teacher extends Person permits EnglishTeacher, ChineseTeacher {
}

可以看到,这两个子类都是直接继承Person的,且在同一个包下面

同时,Teacher又规定了它的两个子类是EnglishTeacherChineseTeacher

代码语言:javascript复制
package com.banmoon.sealecClasses;

public non-sealed class EnglishTeacher extends Teacher {
}
代码语言:javascript复制
package com.banmoon.sealecClasses;

public non-sealed class ChineseTeacher extends Teacher{
}

大家伙应该都已经发现了下面这几个特性

  • 如果父类使用了sealed关键字,那么它就必须要用permits关键字指定子类
  • 子类要么使用finalno-sealed关键字,要么自己再次使用sealed关键字成为一个父类,并指定子类
  • 他们都在同一个包下面,且不允许其它类进行继承

我们来试一下,我们在另一个包创建Engineer,并继承Person

代码语言:javascript复制
package com.banmoon.sealecClasses.other;

import com.banmoon.sealecClasses.Person;

public final class Engineer extends Person {
}

请看下面的图片

5)Record类

Record类,里面的属性是只读的,只提供了获取方法,且提供一个全参的构造函数。

如下有一个UserRecord

代码语言:javascript复制
package com.banmoon.recordClasses;

public record UserRecord(Integer id, String username, String password) {

    public static void main(String[] args) {
        UserRecord user1 = new UserRecord(1, "半月无霜", "abc123");
        System.out.printf("帐号ID:%d,用户名:%s,密码:%s%n", user1.id, user1.username, user1.password);
        UserRecord user2 = new UserRecord(1, "半月无霜", "abc123");
        System.out.printf("帐号ID:%d,用户名:%s,密码:%s%n", user1.id, user1.username, user1.password);
        System.out.println(user1.equals(user2));
    }

}

Record类已经帮我们重写了equals()hashCode()toString()方法

6)NullPointException优化

在以前的JDK版本中,我们有这样的问题,一行代码要是连续get获取对象中的对象。

如果万一没有做好校验,那么就会爆空指针异常,但仅仅只会报出在哪一行。如下面这段代码

代码语言:javascript复制
package com.banmoon.NullPoint;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {

    private User user;

}
代码语言:javascript复制
package com.banmoon.NullPoint;

public class NullPointMain {

    public static void main(String[] args) {
        User user = new User(new User(new User(null)));
        System.out.println(user.getUser().getUser().getUser().getUser());
    }

}

报错NullPointException是这样子的,只告诉了在第几行

那么在JDK17中,这个报错信息会是怎么样的呢

好的,它已经将是哪个方法是null的已经标出来了,这样定位空指针就简单了。

7、ZGC垃圾收集器

ZGC是一种针对大堆和低延迟的垃圾回收器,它的目标是减少垃圾回收期间的停顿时间,并提供可预测和稳定的性能。

目前来说JDK21中,实现了ZGC的分代收集。

这款收集器,先让行业内大佬先行使用,我们持续观望中

三、最后

好了,讲讲为什么突然看起了JDK17呢?

还得是因为SpringBoot3使用了这个版本,要进行学习还是得先简单过一下JDK17中的内容。

我是半月,你我一同共勉!!!

0 人点赞