Java Records:简化数据载体类

Java Records是Java 14中引入的一项新特性,并在Java 16中正式成为标准功能。它的主要目标是提供一种简洁的语法来声明主要用于存储数据的不可变类。在Records出现之前,开发者需要手动编写大量样板代码,如私有final字段、全参构造函数、getter方法以及toString、equals和hashCode方法。而一个Record会自动为我们生成所有这些方法,极大地简化了代码。例如,定义一个表示点的Record只需一行代码:record Point(int x, int y) { }。编译器会自动生成一个包含两个final字段x和y的类,以及相应的访问器、equals、hashCode和toString方法。这减少了代码量,提高了开发效率,并避免了因手动编写可能导致的错误。

Sealed Classes:精细化控制继承

Sealed Classes(密封类)是Java 15的预览特性,并在Java 17中成为正式功能。它允许类和接口限制哪些其他类或接口可以扩展或实现它们。这是通过对permits关键字指定允许的子类来实现的。例如,我们可以定义一个密封类Shape,并只允许Circle和Rectangle继承它:public sealed class Shape permits Circle, Rectangle { }。然后,子类必须被声明为final、sealed或non-sealed。这一特性为类的层次结构提供了更精确的控制,增强了代码的安全性和可维护性。它使开发者能够明确表达设计意图,防止无关类的随意扩展,从而在模式匹配等场景中实现更全面的编译时检查。

Records与Sealed Classes的结合:构建简洁且安全的模型

Records和Sealed Classes的结合使用可以创建出既简洁又安全的数据模型。例如,在定义代数数据类型(ADT)时,我们可以使用密封类作为根类型,然后用Records来实现具体的子类型。这种组合强制了类型的 exhaustiveness( exhaustiveness 检查),意味着编译器可以确保在switch表达式中处理了所有可能的情况。例如,一个密封接口Expr可能允许AddExpr和MultExpr两个Record实现。当使用模式匹配的switch表达式处理Expr时,编译器会检查是否涵盖了所有许可的子类,否则会报错。这极大地减少了因遗漏case而导致的运行时错误,使代码更加健壮。

实际应用与代码设计简化

在实际应用中,Records和Sealed Classes共同作用,显著简化了领域模型的设计。传统的JavaBean模式需要大量重复的getter和setter,而Records消除了数据载体的样板代码。同时,Sealed Classes取代了通过将类声明为final或使用包级私有构造函数等不够直观的方式来限制继承的方法。例如,在构建一个诸如JSON AST(抽象语法树)的模型时,使用密封类定义所有可能的节点类型(如JsonObject, JsonArray, JsonString),并用Record实现每个节点,可以创建一个类型安全、结构清晰且易于扩展(通过修改permits列表)的模型。这种设计范式使代码更易于阅读、维护和推理。

总结

综上所述,Java的Records和Sealed Classes是两个强大的新特性,它们分别从减少样板代码和控制继承关系两个维度简化了代码设计。Records让我们能够用最简洁的方式定义纯粹的数据聚合类,而Sealed Classes则提供了对类层次的精确控制,增强了API的封闭性和安全性。当两者结合使用时,它们为构建表达力强、类型安全且易于维护的领域模型提供了坚实的基础,代表了Java语言向更现代、更简洁的编程范式发展的重要一步。

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐