Java jdk21新增的语法特性(一)
·
一、语言特性
440 Record Patterns ----记录模式
441 Pattern Matching for switch ----针对switch的Pattern Matching for switch
(一) Record Patterns记录模式440
记录模式提供了一种简洁的方式进行模式匹配,它在模式匹配中使用记录类型,并且可以方便地从记录类型中提取字段值。
public record Rectangle(double width, double height) implements Shape {
}
等价于一个包含:
- 两个字段 width 和
height- 对应的访问器 width
()和height()- 自动生成的构造函数和
equals()、hashCode()、toString()方法
记录模式允许你使用结构匹配语法,直接从 record 中解构并提取字段。
if (shape instanceof Rectangle (double width, double height)) {
return width * height;
}
shape instanceof Rectangle(int width, int height)不只是判断shape是Shape,还将其解构为 width 和height- width 和
height是自动绑定的局部变量
案例应用:
//形状接口
public interface Shape {
}
//圆形记录
public record Circle(double radius) implements Shape {
}
//矩形记录
public record Rectangle(double width, double height) implements Shape {
}
测试类:
package d2_record;
public class Main {
public static void main(String[] args) {
Circle c = new Circle(5.0);
System.out.println(String.format("Circle: radius = %.2f", c.radius()));
System.out.println(String.format("Circle: area1 = %.2f", getArea(c)));
System.out.println("----------------------");
System.out.println(String.format("Circle: area2 = %.2f", getArea2(c))+"\n");
Rectangle r = new Rectangle(10.0, 20.0);
System.out.println(String.format("Rectangle: width = %.2f, height = %.2f", r.width(), r.height()));
System.out.println(String.format("Rectangle: area1 = %.2f", getArea(r)));
System.out.println("----------------------");
System.out.println(String.format("Rectangle: area2 = %.2f", getArea2(r)));
}
/**
* 计算面积
* @param shape
* @return
*/
public static double getArea(Shape shape) {
//调用方法获取属性值
if (shape instanceof Circle c) {
return Math.PI * c.radius() * c.radius();
} else if (shape instanceof Rectangle r) {
return r.width() * r.height();
}else {
return 0.0;
}
}
/**
* 计算面积
* @param shape
* @return
*/
public static double getArea2(Shape shape) {
//自动绑定的局部变量,无需再调用方法获取属性值
if (shape instanceof Circle (double radius) ) {
return Math.PI * radius * radius;
}else if (shape instanceof Rectangle (double width, double height)) {
return width * height;
}else {
return 0.0;
}
}
}

如果在运行时,出现这个异常:

解决: 配置项目JDK版本和设置编译器参数

优点: 结合模式匹配,可以更方便地从记录类中获取字段的值并使用。
(二)Pattern Matching for switch的模式匹配441
模式匹配的switch允许在 switch 语句中使用模式匹配。通过这个特性,咱们可以更方便地对变量进行类型判断和提取。
在Java 21中switch的case标签(case label)除了支持枚举常量、字符串常量、整数常量(包括char类型),还支持类型模式(type pattern)与null值。
DK21之前,使用if-else判断
public static String formatter(Object obj) {
String str = "未知类型";
if (obj instanceof String s) {
str = String.format("字符串:%s", s);
} else if (obj instanceof Integer i) {
str = String.format("整数:%d", i);
} else if (obj instanceof Double d) {
str = String.format("浮点型:%f", d);
} else if (obj instanceof Long l) {
str = String.format("长整数:%d", l);
}
return str;
}
JDK21开始,使用带模式匹配的switch直接判断和提取
public static String formatter3(Object obj) {
String str = "未知类型";
switch (obj) {
case String s -> str = String.format("字符串:%s", s);
case Integer i -> str = String.format("整数:%d", i);
case Double d -> str = String.format("浮点型:%f", d);
case Long l -> str = String.format("长整数:%d", l);
default -> throw new IllegalStateException(str);
}
return str;
}
使用switch表达式,并返回值
public static String formatter4(Object obj) {
String str = "未知类型";
return switch (obj) {
case String s -> String.format("字符串:%s", s);
case Integer i -> String.format("整数:%d", i);
case Double d -> String.format("浮点型:%f", d);
case Long l -> String.format("长整数:%d", l);
default -> throw new IllegalStateException(str);
};
}

案例应用:地址记录和学生记录
/**
* Student record
* @param name 姓名
* @param gender 性别
* @param age 年龄
* @param address 地址
*/
public record Student(String name, String gender, int age ,Address address) {
}
/**
* Address record
* @param city 城市
* @param district 区域
* @param street 街道
*/
public record Address(String city, String district,String street) {
}
(1)case标签支持嵌套记录模式
(2) 守卫标签(guarded label)
守卫标签是在case标签中使用布尔表达式语句。
使用
when子句指定守卫(guard),理解为只有当满足条件时才允许执行下去。
(3) switch对enum常量的增强
public static void test(Object obj) {
switch (obj) {
case null -> System.out.println("null");
case Student s -> System.out.println("学生: " + s.name()+" "+s.address().city());
case Long l -> System.out.println("长整型: " + l);
case String s -> System.out.println("字符串: " + s);
default -> System.out.println("未知类型");
}
}
/**
* case标签还支持多重嵌套记录模式(multiple nested record pattern)
* 新版switch表达式
* @param obj
*/
public static void test2(Object obj) {
switch (obj) {
// 匹配Student对象及其属性
case Student(String name,String sex,int age,Address(String city,String district,String street))
-> {
System.out.println("学生: " + name+" "+age);
System.out.println("地址: " + city+" -"+district+" -"+street);
}
default -> System.out.println("未知类型");
}
}
/**
* 守卫标签(guarded label):在case标签中使用布尔表达式语句,以进一步细化匹配条件。
* @param obj
*/
public static void test3(Object obj) {
switch (obj) {
case null -> System.out.println("null");
// 匹配Student对象及其属性
case Student(String name,String sex,int age,Address addr) when (age >= 18)
-> {
System.out.println("学生: " + name+" "+age+"是成年人!");
}
case Student(String name,String sex,int age,Address addr) when(sex.equals("女") && name.length() > 2)
-> System.out.println("学生: " + name+" "+age+"岁,她是女性,未成年!");
default -> System.out.println("未知类型");
}
}
/**
* switch对enum常量的增强:
* @param obj
*/
public static void test4(Object obj) {
switch (obj) {
case Color.RED -> System.out.println("红色");
case Color.GREEN -> System.out.println("绿色");
case Color.BLUE -> System.out.println("蓝色");
case Size s when (s == Size.SMALL) -> System.out.println("小号");
default -> System.out.println("未知类型");
}
}
}
// 枚举类型
enum Color {
RED, GREEN, BLUE;
}
// 枚举类型
enum Size {
SMALL, MEDIUM, LARGE;
}
测试类
public static void main(String[] args) {
Student stu = new Student("张三", "男", 20, new Address("北京","朝阳区","长安街"));
test(stu);
test(123L);
test("Hello");
test(null);
System.out.println("---------------");
test2(stu);
System.out.println("---------------");
Student stu2 = new Student("李菲菲", "女", 17, new Address("北京","朝阳区","长安街"));
test3(stu2);
System.out.println("---------------");
test4(Color.RED);
test4(Size.SMALL);
test4("he");
}

优点:可以更方便地对变量进行类型判断和提取
更多推荐


所有评论(0)