一、语言特性

    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");

    }

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

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐