record类

java 复制代码
import lombok.Data;

import java.io.Serializable;
import java.util.List;
/**
 * 图片收集计划
 */

@Data
public class ImageCollectionPlan implements Serializable {
    
    /**
     * 内容图片搜索任务列表
     */
    private List<ImageSearchTask> contentImageTasks;
    
    /**
     * 插画图片搜索任务列表
     */
    private List<IllustrationTask> illustrationTasks;
    
    /**
     * 架构图生成任务列表
     */
    private List<DiagramTask> diagramTasks;
    
    /**
     * Logo生成任务列表
     */
    private List<LogoTask> logoTasks;
    
    /**
     * 内容图片搜索任务
     * 对应 ImageSearchTool.searchContentImages(String query)
     */
    public record ImageSearchTask(String query) implements Serializable {}
    
    /**
     * 插画图片搜索任务
     * 对应 UndrawIllustrationTool.searchIllustrations(String query)
     */
    public record IllustrationTask(String query) implements Serializable {}
    
    /**
     * 架构图生成任务
     * 对应 MermaidDiagramTool.generateMermaidDiagram(String mermaidCode, String description)
     */
    public record DiagramTask(String mermaidCode, String description) implements Serializable {}
    
    /**
     * Logo生成任务
     * 对应 LogoGeneratorTool.generateLogos(String description)
     */
    public record LogoTask(String description) implements Serializable {}
}

如何理解record

一、record 是什么?

record 是 Java 16 引入的一种特殊的类 ,专门用于创建不可变的数据载体(也叫 "数据类")。它的核心目的是简化只用来存储数据、不需要复杂业务逻辑的类的编写。

简单来说:你定义一个 record,Java 会自动帮你生成:

  1. 所有字段的私有 final 成员变量
  2. 全参构造方法
  3. 每个字段的 getter 方法(注意:getter 名不是 getXxx(),而是直接用字段名,比如 query() 而不是 getQuery()
  4. 重写的 equals()hashCode()(基于所有字段)
  5. 重写的 toString()(包含所有字段名和值)

二、结合代码理解 record 的用法

在你的代码中,ImageSearchTaskIllustrationTask 等都是用 record 定义的,我们以 ImageSearchTask 为例拆解:

java

运行

java 复制代码
// 定义一个 record,括号里是它的核心字段
public record ImageSearchTask(String query) implements Serializable {}

这一行代码,等价于手动编写下面这段冗长的代码:

java

运行

java 复制代码
public final class ImageSearchTask implements Serializable {
    // 私有、不可变的成员变量
    private final String query;

    // 全参构造方法
    public ImageSearchTask(String query) {
        this.query = query;
    }

    // getter 方法(无 get 前缀)
    public String query() {
        return this.query;
    }

    // 自动生成的 equals 和 hashCode
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ImageSearchTask that = (ImageSearchTask) o;
        return Objects.equals(query, that.query);
    }

    @Override
    public int hashCode() {
        return Objects.hash(query);
    }

    // 自动生成的 toString
    @Override
    public String toString() {
        return "ImageSearchTask[query=" + query + "]";
    }
}

再看更复杂的 DiagramTask

java

运行

java 复制代码
public record DiagramTask(String mermaidCode, String description) implements Serializable {}

它会自动生成包含 mermaidCodedescription 两个字段的构造方法、mermaidCode()/description() getter、以及基于这两个字段的 equals/hashCode/toString

java 复制代码
import java.io.Serializable;
import java.util.Objects;

// record 隐式为 final 类,且默认继承 java.lang.Record(不能手动改)
public final class DiagramTask implements Serializable {
    // 1. 自动生成:所有字段为 private final(不可变)
    private final String mermaidCode;
    private final String description;

    // 2. 自动生成:全参构造方法(参数顺序与 record 定义的字段顺序完全一致)
    public DiagramTask(String mermaidCode, String description) {
        // 严格按参数顺序赋值,无默认值,必须传全参
        this.mermaidCode = mermaidCode;
        this.description = description;
    }

    // 3. 自动生成:getter 方法(无 get 前缀,直接用字段名作为方法名)
    public String mermaidCode() {
        return this.mermaidCode;
    }

    public String description() {
        return this.description;
    }

    // 4. 自动生成:equals() 方法(基于所有字段的值比较)
    @Override
    public boolean equals(Object o) {
        // 第一步:引用地址相同,直接返回 true
        if (this == o) return true;
        // 第二步:对象为 null 或类型不一致,返回 false(严格匹配类类型,不考虑子类)
        if (o == null || getClass() != o.getClass()) return false;
        // 第三步:强转后逐个比较字段值
        DiagramTask that = (DiagramTask) o;
        return Objects.equals(mermaidCode, that.mermaidCode) 
                && Objects.equals(description, that.description);
    }

    // 5. 自动生成:hashCode() 方法(基于所有字段的哈希值计算)
    @Override
    public int hashCode() {
        // 按字段顺序组合哈希值,只要有一个字段不同,哈希值大概率不同
        return Objects.hash(mermaidCode, description);
    }

    // 6. 自动生成:toString() 方法(包含类名 + 所有字段名和值)
    @Override
    public String toString() {
        // 格式固定:类名[字段名1=值1, 字段名2=值2]
        return "DiagramTask[" +
                "mermaidCode=" + mermaidCode +
                ", description=" + description +
                "]";
    }
}

三、record 的核心特点(新手必知)

  1. 不可变性record 的字段默认是 final 的,创建对象后无法修改(比如创建 ImageSearchTask 后,不能改它的 query 值),这符合 "数据载体" 的设计初衷。
  2. 简洁性:用一行代码替代几十行模板代码,大幅减少冗余。
  3. 可实现接口 :比如你的代码中所有 record 都实现了 Serializable,这是允许的。
  4. 不能继承 / 被继承record 隐式是 final 的,不能作为父类;也不能继承其他类(但可以实现接口)。
  5. 适合场景:只用来存储数据、无业务逻辑的类(比如 DTO、VO、数据传输对象、任务参数类等),就像你代码中的各种 Task 类(只存查询词、描述等数据)。

四、为什么这段代码要用 record

ImageCollectionPlan 中的 ImageSearchTaskIllustrationTask 等都是 "任务参数类":

  • ImageSearchTask 只需要存储 "图片搜索的关键词(query)"
  • DiagramTask 只需要存储 "mermaid 代码" 和 "描述"
  • 这些类不需要修改字段、不需要复杂方法,只需要存储数据 + 基础的比较 / 打印功能

record 正好契合这个需求,既简洁又符合 Java 最佳实践。

总结

  1. record 是 Java 简化 "数据载体类" 编写的语法糖,自动生成构造方法、getter、equals/hashCode/toString。
  2. record 的字段默认不可变(final),适合存储无需修改的纯数据。
  3. 代码中的各类 Task 用 record 定义,是因为它们仅作为 "任务参数容器",无业务逻辑,完美匹配 record 的使用场景。
相关推荐
jiayong232 小时前
可视化流程设计器技术对比:钉钉风格 vs BPMN
java·前端·钉钉
左左右右左右摇晃2 小时前
MyBatis & MyBatis-Plus 面试题整理
java·笔记
2501_921649492 小时前
全球股票行情API:如何高效获取实时与逐笔成交数据
开发语言·后端·python·金融·restful
xiaoye37082 小时前
CentOS 7 搭建Maven私服
java·maven
甘露s2 小时前
新手入门:传统 Web 开发与前后端分离开发的区别
开发语言·前端·后端·web
快乐得小萝卜2 小时前
记录: python-cpp数据验证
开发语言·python
lsx2024062 小时前
C语言中的递归
开发语言
北极糊的狐2 小时前
MySQL常见报错分析及解决方案总结(42)---ERROR 1142 (42000): SELECT command denied
java·mysql·adb·myeclipse