JDK17的新特性写法
一、介绍
JDK 17 是 Java Development Kit(Java 开发工具包)的一个版本,是 Oracle 公司提供的 Java SE(Java 平台,标准版)的一部分。以下是 JDK 17 的一些基本信息:
- 版本号:JDK 17 的完整版本号是 17,它是 Java SE 17 的版本。
- 发布日期:JDK 17 v17.0.0 在 2021 年 9 月 14 日正式发布。
- LTS 版本:JDK 17 被标记为 “LTS”(长期支持)版本。LTS 版本提供长期支持和维护,适合用于生产环境。
- 特性更新:JDK 17 引入了一些新的特性、改进和增强,包括但不限于密封类、基础类型的模式匹配、日期时间API的升级等。
- 垃圾回收器:JDK 17 包含了多种垃圾回收器,包括 ZGC、G1GC、ParallelGC 等,以满足不同场景下的需求。
二、新特性
1)switch
可以不用再写break
了,可以进行简化
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
关键字还支持了对类的类型进行判断,比如
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
,十分影响阅读,如同下面这样
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, "半月无霜");
}
}
但现在可以通过"""..."""
,三个引号就可以得到解决,看着十分的清爽。
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
关键字后,还需要带一个强转,例如下面的这段代码
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 {
}
这个父类有两个直接子类,Student
和Teacher
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
又规定了它的两个子类是EnglishTeacher
,ChineseTeacher
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
关键字指定子类 - 子类要么使用
final
、no-sealed
关键字,要么自己再次使用sealed
关键字成为一个父类,并指定子类 - 他们都在同一个包下面,且不允许其它类进行继承
我们来试一下,我们在另一个包创建Engineer
,并继承Person
类
package com.banmoon.sealecClasses.other;
import com.banmoon.sealecClasses.Person;
public final class Engineer extends Person {
}
请看下面的图片
5)Record类
Record
类,里面的属性是只读的,只提供了获取方法,且提供一个全参的构造函数。
如下有一个UserRecord
类
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
中的内容。
我是半月,你我一同共勉!!!