java17新特性简单介绍
前言
本项目使用的 IDE 为 IDEA 2023.3.3(社区版)。
文本块
java17之前的写法,双引号需要转义,换行需要\n,需要加号拼接
复制public class TestString {
public static void main(String[] args) {
String json = "{\n" +
" \"id\": \"1\",\n" +
" \"name\": \"菜鸟教程\",\n" +
" \"url\": \"www.runoob.com\"\n" +
"}";
System.out.println(json);
}
}
java17的写法,可读性更好,一目了然。
复制public class TestString {
public static void main(String[] args) {
String json = """
{
"id": "1",
"name": "菜鸟教程",
"url": "www.runoob.com"
}
""";
System.out.println(json);
}
}
像传统的字符串一样,文本块是字符串的一种常量表达式。不同于传统字符串的是,在编译期,文本块要顺序通过如下三个不同的编译步骤:
- 为了降低不同平台间换行符的表达差异,编译器把文本内容里的换行符统一转换成 LF(\u000A);
- 为了能够处理Java源代码里的缩进空格,要删除所有文本内容行和结束分隔符共享的前导空格,以及所有文本内容行的尾部空格;
- 最后处理转义字符,这样开发人员编写的转义序列就不会在第一步和第二步被修改或删除。
通过反编译可以看到,文本块本质上也是语法糖。
switch表达式
java17之前的写法,必须要加break
复制public class TestSwitch {
public static void main(String[] args) {
test("+",5,6);
}
private static void test(String sign, int num1, int num2) {
int ret = 0;
switch (sign) {
case "+":
ret = num1 + num2;
break;
case "-":
ret = num1 - num2;
break;
case "*":
ret = num1 * num2;
break;
case "/":
ret = num1 / num2;
break;
default:
break;
}
System.out.println("ret: " + ret);
}
}
java17的写法,switch必须覆盖所有可能的情况,如果是枚举,就必须包含所有值
复制public class TestSwitch {
public static void main(String[] args) {
test1("*", 5, 6);
}
private static void test1(String sign, int num1, int num2) {
int ret = switch (sign) {
case "+" -> {
System.out.println("this is add");
yield num1 + num2;// 下面的是简化写法
}
case "-" -> num1 - num2;
case "*" -> num1 * num2;
case "/" -> num1 / num2;
default -> throw new IllegalStateException("Unexpected value: " + sign);
};
System.out.println("ret: " + ret);
}
}
本质上也是编译器的语法糖
record类
复制public class TestRecord {
public static void main(String[] args) {
Person person = new Person("lisi", "123");
System.out.println(person.username());// 不是标准的 getter
System.out.println(person);
}
public record Person(String username,String password){
}
}
会帮我们生成构造器,toString()方法,equals()方法,对象不可变,没有 setter 及标准的 getter,功能不如 lombok 强大。
密封类
在这之前一个类要么是可以被extends的,要么是final的,只有这两种选项。密封类可以控制有哪些类可以对超类进行继承。子类需要指明它是final,non-sealed或sealed的,父类不能控制子类是否可以被继承。
复制public class TestSealed {
public static void main(String[] args) {
new TestSealed().test();
}
public void test() {
Animal animal = new WildPig();
System.out.println(animal);
}
/**
* 动物
*/
sealed class Animal permits Dog, Cat, Pig {
}
/**
* 狗
*/
final class Dog extends Animal {
}
/**
* 猫
*/
non-sealed class Cat extends Animal {
}
/**
* 猪
*/
sealed class Pig extends Animal permits WildPig {
}
/**
* 野猪
*/
final class WildPig extends Pig {
}
}
instanceof模式匹配
java17之前必须手动进行类转换
复制public class TestInstanceOf {
public static void main(String[] args) {
test1("hello");
test1(123);
}
private static void test1(Object obj) {
if (obj instanceof String) {
int length = ((String) obj).length();
System.out.println(length);
}
}
}
java17可以简写
复制public class TestInstanceOf {
public static void main(String[] args) {
test1("hello");
}
private static void test1(Object obj) {
if (obj instanceof String str) {
System.out.println(str.length());
}
}
}
空指针异常打印增强
复制import lombok.Data;
public class TestNullPointerException {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.getAddress().getProvince().getCode());
}
@Data
private static class Person {
private Address address;
}
@Data
private static class Address {
private Province province;
}
@Data
private static class Province {
private String name;
private String code;
}
}
java17之前的异常信息如下,仅显示发生异常的行号,但不知道具体哪个方法调用时产生的异常,必须通过调试的方式找到。
复制Exception in thread "main" java.lang.NullPointerException
at com.imooc.TestNullPointerException.main(TestNullPointerException.java:9)
java17的异常信息如下,会显示出现异常的精确位置。
复制Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.imooc.TestNullPointerException$Address.getProvince()" because the return value of "com.imooc.TestNullPointerException$Person.getAddress()" is null
at com.imooc.TestNullPointerException.main(TestNullPointerException.java:8)
Stream增强
java17之前
复制public class TestStream {
public static void main(String[] args) {
List<String> languages = Stream.of("java", "python").collect(Collectors.toList());
System.out.println(languages);
}
}
java17增加了一个 toList() 方法
复制public class TestStream {
public static void main(String[] args) {
List<String> languages = Stream.of("java", "python").toList();
System.out.println(languages);
}
}
矢量运算
复制private static void testFloatVector() {
float[] data = {0.1f, 0.2f};
FloatVector floatVector = FloatVector.fromArray(FloatVector.SPECIES_64, data, 0);
System.out.println(floatVector.mul(floatVector));
}
报错如下
复制java: package jdk.incubator.vector is not visible
(package jdk.incubator.vector is declared in module jdk.incubator.vector, which is not in the module graph)
添加编译参数 --add-modules jdk.incubator.vector

还报错
复制Error: Unable to initialize main class com.imooc.TestFloatVector
Caused by: java.lang.NoClassDefFoundError: jdk/incubator/vector/Vector
添加运行时VM参数 --add-modules jdk.incubator.vector

运行结果为
复制[0.010000001, 0.040000003]
参考
Java 17的这些新特性不看后悔
深入剖析Java新特性-02文字块:怎么编写所见即所得的字符串?
java9系列(六)HTTP/2 Client (Incubator)
Linux和Windows下JDK17下载地址
Mac下JDK17下载地址
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
2021-03-08 java中Object的默认hashCode方法实现原理