当前位置: 首页 > article >正文

JDK 21 与Springboot3的新特性

JDK 21 是 Java 的最新长期支持(LTS)版本,引入了许多新特性,主要包括:

  • Record:简化不可变类的定义。

  • Switch 表达式:增强 Switch 语句的功能。

  • 文本块:简化多行字符串的定义。

  • var 关键字:局部变量类型推断。

  • 密闭类(Sealed Classes):限制类的继承。

  • 模式匹配:简化 instanceof 和类型转换。

1.Record类

Record 是 JDK 14 引入的特性,用于简化不可变类的定义。它自动生成 equals()hashCode()toString() 等方法,类似于 Lombok 的 @Data 注解。Record默认创建不可变的数据结构,字段默认为final,因此非常适合数据完整性至关重要的使用场景 示例

public record User(String name, int age) {}

等同于以下代码:

public final class User {
    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String name() { return name; }
    public int age() { return age; }

    @Override
    public boolean equals(Object o) { ... }
    @Override
    public int hashCode() { ... }
    @Override
    public String toString() { ... }
}

定义一个简单的 Record:

public record Point(int x, int y) {}

使用 Record:

Point p = new Point(10, 20);
System.out.println(p.x()); // 输出 10
System.out.println(p.y()); // 输出 20

Record - 实例方法与静态方法

public record Point(int x, int y) {
    // 实例方法
    public double distanceFromOrigin() {
        return Math.sqrt(x * x + y * y);
    }

    // 静态方法
    public static Point origin() {
        return new Point(0, 0);
    }
}


//调用方法
public class Main {
    public static void main(String[] args) {
        // 创建一个Point实例
        Point point = new Point(3, 4);

        // 调用实例方法distanceFromOrigin()
        double distance = point.distanceFromOrigin();
        System.out.println("Distance from origin: " + distance);

        // 调用静态方法origin()
        Point origin = Point.origin();
        System.out.println("Origin: (" + origin.x() + ", " + origin.y() + ")");
    }
}

Record - 三种构造方法

Record 支持三种构造方法:

  1. 规范构造方法:默认生成。

  2. 紧凑构造方法:用于参数验证。

Record实现接口

Java Record可以像普通类一样实现接口,并重写接口中的方法。

// 定义一个接口
public interface PrintInterface {
    void print();
}

// 定义一个Record并实现接口
public record ProductRecord(Integer id, String name, Integer qty) implements PrintInterface {
    @Override
    public void print() {
        StringJoiner joiner = new StringJoiner("-");
        joiner.add(id.toString()).add(name).add(qty.toString());
        System.out.println("商品信息 = " + joiner);
    }
}

// 测试
public class Main {
    public static void main(String[] args) {
        ProductRecord productRecord = new ProductRecord(1001, "手机", 200);
        productRecord.print(); // 输出:商品信息 = 1001-手机-200
    }
}

Record的继承

Java Record是隐式final的,不能被继承。这意味着你不能创建一个继承自Record的子类。Record的所有字段和方法在编译时已经固定,无法通过继承来扩展。

示例:

record Person(String name, int age) {} // 基础Record

// 以下代码会导致编译错误,Record不能被继承
// record Student(String name, int age, String school) extends Person {}

Record的灵活性

尽管Record不能被继承,但它可以实现多个接口。这使得Record在多态场景下具有很好的灵活性。示例:

public interface PrintInterface {
    void print();
}

public interface LogInterface {
    void log();
}

public record ProductRecord(Integer id, String name, Integer qty) implements PrintInterface, LogInterface {
    @Override
    public void print() {
        System.out.println("商品信息 = " + id + "-" + name + "-" + qty);
    }

    @Override
    public void log() {
        System.out.println("日志记录:商品ID = " + id);
    }
}

public class Main {
    public static void main(String[] args) {
        ProductRecord productRecord = new ProductRecord(1001, "手机", 200);
        productRecord.print(); // 输出商品信息
        productRecord.log();   // 输出日志记录
    }
}

Record 与 Lombok 对比

特性RecordLombok (@Data)
不可变性需要手动设置 final
代码简洁性更简洁需要注解
功能扩展有限更灵活
兼容性JDK 14+兼容所有 JDK 版本

Record 总结

  • Java Record可以实现接口,并重写接口中的方法,这使得Record可以参与多态。

  • Java Record不能被继承,因为它是隐式final的。

  • Record通过实现接口可以增强其灵活性和可用性。

如果你需要更复杂的继承关系或可变的数据结构,建议使用普通类而不是Record。

2. Switch 箭头表达式

JDK 12 引入了 Switch 表达式,JDK 13 引入了 yield 关键字。

String day = "MON";
String result = switch (day) {
    case "MON", "TUE", "WED", "THU", "FRI" -> "Weekday";
    case "SAT", "SUN" -> "Weekend";
    default -> throw new IllegalArgumentException("Invalid day");
};

Switch yield

yield 用于在 Switch 表达式中返回值:

1. yield的作用

yield关键字用于从switch代码块中返回一个值。它类似于函数中的return语句,但只能在switch代码块中使用。使用yield可以将一个值传递给switch表达式的调用者。

yield可以用于更复杂的逻辑中,例如在代码块中进行计算后返回结果。

2.yieldreturn的区别

  • yield

    • 只能在switch代码块中使用。

    • 用于从switch代码块中返回一个值。

    • 使得switch表达式可以作为一个整体返回一个值。

  • return

    • 可以在任何方法中使用。

    • 用于从方法中返回一个值。

    • 不能在switch代码块中直接使用(除非switch代码块在方法中)。

3.switch表达式的语法

switch表达式可以包含多个case语句,每个case语句可以使用->{}语法。如果使用{}语法,则可以在代码块中使用yield返回值。

String day = "MON";
String result = switch (day) {
    case "MON", "TUE", "WED", "THU", "FRI" -> {
        System.out.println("It's a weekday");
        yield "Weekday";
    }
    case "SAT", "SUN" -> {
        System.out.println("It's a weekend");
        yield "Weekend";
    }
    default -> throw new IllegalArgumentException("Invalid day");
};

Switch 代码块和 yield

Switch 表达式支持代码块:

String day = "MON";
String result = switch (day) {
    case "MON", "TUE", "WED", "THU", "FRI" -> {
        System.out.println("It's a weekday");
        yield "Weekday";
    }
    case "SAT", "SUN" -> {
        System.out.println("It's a weekend");
        yield "Weekend";
    }
    default -> throw new IllegalArgumentException("Invalid day");
};

Switch Record

Switch 表达式支持 Record 模式匹配:

record Point(int x, int y) {}

static String checkPoint(Object obj) {
    return switch (obj) {
        case Point(int x, int y) -> "Point: (" + x + ", " + y + ")";
        default -> "Unknown";
    };
}

3.文本块 - 创建文本块 

文本块(Text Blocks)是 JDK 13 引入的特性,用于简化多行字符串的定义。示例

String json = """
    {
        "name": "John",
        "age": 30
    }
    """;

文本块 - 方法

文本块支持字符串方法:

String text = """
    Hello,
    World!
    """;
System.out.println(text.stripIndent()); // 去除缩进

4.var 关键字

var 是 JDK 10 引入的关键字,用于局部变量类型推断。

var list = new ArrayList<String>();
list.add("Hello");
list.add("World");

var i = 0;
var i = "asdasd";

Sealed 密闭类

密闭类(Sealed Classes)是 JDK 15 引入的特性,用于限制类的继承。

密封接口使用sealed关键字定义,并通过permits关键字指定允许实现该类了的具体类或接口。你的代码中已经正确地使用了Circle 和 Square 

//Shape permits Circle, Square 这个表示这个类只能被  Circle 和 Square  继承(这主要用与框架和底层)
public sealed class Shape permits Circle, Square {   
    // 父类
}

public final class Circle extends Shape {
    // 子类
}

public final class Square extends Shape {
    // 子类
}

Sealed 密闭接口

密闭接口(Sealed Interfaces)与密闭类类似,用于限制接口的实现。

密封接口使用sealed关键字定义,并通过permits关键字指定了允许实现该接口的具体类或接口。你的代码中已经正确地使用了sealedpermits

//Shape permits Circle, Square 这个表示 这个接口只能被Circle 和 Square 实现 (这主要用与框架和底层)
public sealed interface Animal permits Dog, Cat {
    // 父接口
}

public final class Dog implements Animal {
    // 实现类
}

public final class Cat implements Animal {
    // 实现类
}


http://www.kler.cn/a/564656.html

相关文章:

  • 三菱FX5U PLC工字轮排线算法(ST源代码)
  • undo log、redo log和bin log详解
  • springai系列(二)从0开始搭建和接入azure-openai实现智能问答
  • 基于springboot+vue的融合多源高校画像数据与协同过滤算法的高考择校推荐系统
  • 课程2. 用PyTorch训练神经网络与梯度下降
  • 关于回溯算法中的剪枝是否需要for循环的总结归纳
  • Docker如何启动SuperSet实现报表功能
  • GPT 与BERT的异同
  • 事务性质ACID
  • WPF13-MVVM进阶
  • java面试项目介绍,详细说明
  • HarmonyOS NEXT 原生应用/元服务-自定义运行/调试配置
  • Sqli-labs
  • 港澳金融机构入股境内保险公司门槛取消
  • # C# 中堆(Heap)与栈(Stack)的区别
  • 可以免费无限次下载PPT的网站
  • 怎么快速对mysql全表扫描
  • C#上位机--二级运算符
  • C语言综合案例:学生成绩管理系统
  • 【FL0080】基于SSM和微信小程序的宠物寄养平台