如何用 Lombok @With 实现不可变对象中集合属性的精准替换与深拷贝

酷宇大大_6689

酷宇大大_6689

2026-06-03

678人浏览

原创

本文详解如何借助 Lombok 的 @With 注解,为含集合字段(如 Set)的不可变值对象(@Value)生成语义清晰、线程安全的“with 方法”,实现单字段(尤其是集合)的原子级替换,避免 toBuilder() 在集合重置场景下的失效问题。

本文详解如何借助 lombok 的 `@with` 注解,为含集合字段(如 `set`)的不可变值对象(`@value`)生成语义清晰、线程安全的“with 方法”,实现单字段(尤其是集合)的原子级替换,避免 `tobuilder()` 在集合重置场景下的失效问题。

在使用 Lombok @Value + @Builder(toBuilder = true) 构建不可变 DTO 时,开发者常期望通过 .toBuilder().skills(...).build() 替换整个集合,但实际运行中会发现:.skills(Collection) 并不会清空原有集合并赋新值,而是被 @Singular 的累积逻辑覆盖(即追加而非替换)。正如示例所示,即使显式调用 .skills(Collections.emptySet()),输出仍保留 "Java", "Spring" —— 这是因为 @Singular 仅提供 skill(String)(单元素追加)和 skills(Collection)(批量追加),不支持“覆盖式重设”。

此时,@With 是更精准、更符合不可变语义的解决方案。它为指定字段生成 withXxx(...) 方法,该方法返回一个全新实例,且对字段执行直接赋值替换(非合并),天然支持集合的整体更新。

✅ 正确用法:@With 替代 toBuilder() 处理集合重置

import lombok.Value;
import lombok.Builder;
import lombok.With;
import java.util.Set;
import java.util.Collections;

@Value
@Builder
public class Person {
    String name;

    // 关键:为 skills 字段启用 @With,同时保留 @Singular 用于构建时的便捷添加
    @With
    @Singular
    Set<string> skills;
}</string>

使用示例:

造梦神码AgentMA
造梦神码AgentMA

造梦神码AgentMA是一款零代码AI应用开发智能体工具。

下载
Person john = Person.builder()
        .name("John")
        .build();
System.out.println(john); 
// 输出:Person(name=John, skills=[])

// ✅ 使用 withSkills() 直接替换整个集合(深拷贝语义)
Person johnUpgraded = john.withSkills(Set.of("Java", "Spring"));
System.out.println(johnUpgraded);
// 输出:Person(name=John, skills=[Java, Spring])

// ✅ 精准清空:传入空集合,彻底替换,无残留
Person johnDowngraded = johnUpgraded.withSkills(Collections.emptySet());
System.out.println(johnDowngraded);
// 输出:Person(name=John, skills=[])

⚠️ 重要注意事项:

  • @With 默认仅对非 final 字段生效。由于 @Value 自动生成 final 字段,需显式禁用 final 修饰或改用 @Data + 手动保证不可变性;更推荐方案是:移除 @Value,改用 @Data + @Builder + @With,并通过构造器/@AllArgsConstructor 控制实例创建入口,确保字段逻辑不可变。
  • 若坚持使用 @Value,可配合 lombok.config 全局启用:
    lombok.with.flag = true(强制为所有字段生成 with 方法)
    或在字段上显式标注:@With(AccessLevel.PUBLIC)。
  • @With 生成的是浅拷贝语义的不可变更新:它复制对象本身并替换目标字段引用,但不递归克隆字段内部对象(如 skills 中的 String 是不可变的,安全;若为自定义对象集合,则需确保其自身不可变或已深拷贝)。

? 对比总结:何时选 @With?何时选 toBuilder()?

场景 推荐方式 原因
单字段整体替换(尤其集合清空/全量更新) withXxx(newCollection) 语义明确、无副作用、代码扁平
多字段增量修改 + 链式构建 toBuilder().field1().field2().build() 适合初始化后微调多个属性
嵌套对象深层更新(如 Person → Address → City) 组合 withAddress(address.withCity("Beijing")) @With 天然支持链式嵌套,比多层 toBuilder() 更简洁

综上,当你的核心诉求是安全、可控、可读地替换不可变对象中的集合属性时,@With 不仅可行,更是 Lombok 生态中针对该问题的首选惯用模式。它让不可变更新从“规避陷阱”变为“直觉编码”,显著提升领域模型的表达力与维护性。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

9797

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

6942

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6132

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1064

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

888

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1296

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2569

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

19891

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1155

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习