Java Record的使用场景分析
目录
- 一、前言
- 二、学习内容:
- 三、问题描述
- 四、解决方案:
- 4.1 为什么引入Record
- 4.2 Record与Class区别
- 4.3 语法与使用场景
- 五、总结:
- 5.1 场景使用
- 5.2 字段的定义
一、前言
- 学习新特性Record的作用
二、学习内容:
- Record与Class的区别以及Record使用场景
三、问题描述
- 为什么引入Record以及Record的作用
四、解决方案:
4.1 为什么引入Record
Java 引入 record 的主要原因是为了简化创建不可变数据类的过程,并提高代码的可读性和维护性。
以下是一些具体的原因:
减少样板代码:
- record 自动生成构造器、equals()、hashCode() 和 toString() 方法,以及每个字段的 getter方法,这样开发人员就可以专注编程于业务逻辑而不是样板代码。
不可变性:
- record 的所有字段默认是 final 的,这意味着它们是不可变的。这有助于创建线程安全和易于管理的数据模型。
简洁性:
- record 允许你用更少的代码来定义数据类,使得类的定义更加清晰和简洁。
性能优化:
- record 类型可能 受到编译器的特定优化,例如更有效的内存布局,从而可能带来性能上的提升。
模式匹配的支持:
- record 在模式匹配方面有更好的支持,这在 Java 14 及以后的版本中变得更加重要,尤其是在使用结构化绑定和改进的 switch表达式时。
易于调试:
- 由于 record 自动提供了 toString() 方法,因此在调试时可以更容易地查看对象的状态。
明确的意图:
- 使用 record 明确地表明了类的目的是作为一个简单的数据载体,这对于其他开发人员阅读代码时是有帮助的。
4.2 Record与Class区别
- 观察下面Class代码与Record代码的区别
- Class
package org.example.recodes; import java.util.Objects; public class Cat { String name; public String getName() { return name; } public Cat(String name) { this.name = name; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Cat cat = (Cat) o; return Objects.equals(name, cat.name); } @Override public int hashCode() { return Objects.hash(name); } }
- Record
package org.example.recodes; public record RecordCat(String name) { }
上面两段代码是等效的
record 自动生成构造器、equals()、hashCode() 和 toString() 方法,以及每个字段的 getter方法
我们运行一下下面代码看看区别
package org.example.recodes; public class Main { public static void main(String[] args) { Cat cat = new Cat("mimi"); System.out.println(cat.getName()); System.out.println(cat); RecordCat recordCat = new RecordCat("momo"); System.out.println(recordCat.name()); System.out.println(recordCat); } }
结果如下:
4.3 语法与使用场景
适用于那些仅用于存储数据而没有复杂业务逻辑的情况
结构体里面可扩展内容如下
⭐️Record所有字段默认是final
- 非静态字段:
非静态字段
要通过构造器(隐式final)去创建,不能在结构体里面自定义- 你不能直接在 record 结构体中手动添加非 final 的字段。
- 如果你需要在结构体自定义的字段,推荐使用 class。
// 构造传入 public record Person(String name, int age) { // 这是合法的,因为字段在声明中定义 // 不合法:不能再这里定义其他字段 // private final String address; // 这将导致编译错误 // 可以添加额外的方法 public String introduce() { return String.format("My name is %s and I am %d years old.", name, age); } }
- 实例方法:
- 除了 record 自动生成的方法外,你可以添加自己的实例方法来扩展 record 的功能。这些方法可以实现特定的业务逻辑或操作。
- 静态成员:
- 你可以在 record 中添加静态方法,这些方法通常用于工厂模式,即创建 record 实例的替代构造方式。
- 可以添加静态字段
- 可以添加静态内部类
public record Person(String name, int age) { // 静态字段 private static final String DEFAU编程客栈LT_COUNTRY = "Unknown"; // 静态方法 public static Person createDefaultPerson() { return new Person("Anonymous", 0); } // 静态内部类 public static class PersonBuilder { private String name; private int age; public PersonBuilder withName(String name) { this.name = name; return this; } public Person build() { return new Person(name, age); } } // 实例方法 public String introduce() { return name + " is " + age + " years old"; } } // 使用示例 public class Main { public void example() { // 使用静态方法 Person defaultPerson = Person.createDefaultPerson(); // 使用静态内部类 Person cwww.devze.comustomPerson = new Person.PersonBuilder() .withName("John") .build(); } }
- 私有方法:
- 私有方法可以用来封装 record 内部的实现细节,例如辅助计算或验证逻辑。
- 嵌套类和内部类:
- record 可以包含嵌套类和内部类,这些类可以用来定义相关的类型,比如枚举类型或其他辅助类。
- 接口实现:
- record 可以实现一个或多个接口,这样就可以提供接口中定义的方法的实现。
- 注解:
- record编程客栈 可以使用注解来标记,这对于框架集成、元数据处理等非常有用。
- 泛型:
- record 支持泛型,允许你定义泛型参数,从而创建通用的 record 类型。
- 覆盖默认方法:
- 尽管 record 自动生成了一些方法,如 equals()、hashCode() 和toString(),你仍然可以覆盖这些方法以提供不同的实现。
五、总结:
5.1 场景使用
简单的数据使用
默认只有Getter方法
record Point(int x, int y) { // 无需显式定义构造器、equals()、hashCode() 或 toString() }
public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Point point = (Point) o; return x == point.x && y == point.y; } @Override public int hashCode() { return Objects.hash(x, y); } @Override public String toString() { return "Point{" + "x=" + x + ", y=" + y + '}'; } }
5.2 字段的定义
在 Java 记录中,所有字段都必须在记录的参数列表中定义。
记录是不可变的:字段一旦赋值,不能被修改。 无法在记录内部定义额外的 private final 字段。下面是相关解释
隐式 final:
- 所有记录字段默认是 final,
这意味着它们一旦被初始化,就不能再被修改
。
只能通过构造器定义:
- 记录中的字段必须在
记录声明的紧随其后的参数列表中定义
,不能在记录的体内再次定义或声明。 - 这意味着
无法手动添加如 private final 字段
,直接在类体内定义是非法的。
自动构造器和访问器:
- Java 会为记录自动生成构造器,以及每个字段的访问器方法(getter)。因此,您不需要手动编写 getter 方法。
public record Person(String name, int age) { // 这是合法的,因为字段在声明中定义 // 不合法:不能再这里定义其他字段 android // private final String address; // 这将导致编译错误 // 可以添加额外的方法 public String introduce() { return String.format("My name is %s and I am %d years old.", name, age); } } // 使用记录的主函数 public class Main { public static void main(String[] args) { Person person = new Person("Alice", 30); System.out.println(person.introduce()); // 输出:My name is Alice and I am 30 years old. } }
(后续有遇到问题再添加)
到此这篇关于Java Record的使用 的文章就介绍到这了,更多相关java record使用 内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论