@Builder注解详解:巧妙避开常见的陷阱

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

🎏:你只管努力,剩下的交给时间

🏠 :小破站

@Builder注解详解:巧妙避开常见的陷阱

    • 前言
    • 1. @Builder的基本使用
      • 使用示例
        • 示例类
        • 创建对象
      • 主要功能
      • 高级用法
        • 自定义构建方法
        • 使用 `@Builder.Default`
      • 依赖配置
        • Maven
        • Gradle
    • 2. 常见的隐藏陷阱
    • 3. 实用的解决方案和最佳实践
      • 知识点总结

前言

在Java开发中,我们经常会遇到需要创建复杂对象的情况。传统的构造函数和setter方法有时显得繁琐且不直观。这时候,Lombok的@Builder注解无疑成为了我们的救星,简化了对象创建的过程。然而,正所谓"世上没有免费的午餐",在享受@Builder带来的便利时,我们也需要警惕那些潜藏的陷阱。今天,让我们一起揭开@Builder的神秘面纱,深入了解它的工作机制和常见问题,避免掉进那些意想不到的坑里。

1. @Builder的基本使用

@Builder 是 Lombok 库中的一个注解,用于实现 Builder 模式。Builder 模式是一种设计模式,通过提供一种灵活的方式来创建对象,尤其是在对象的构造参数较多时。Lombok 的 @Builder 注解可以自动生成一个内部 Builder 类,以及对应的构建方法,从而简化代码的编写。

使用示例

以下是 @Builder 的基本使用示例:

示例类
import lombok.Builder;
import lombok.ToString;

@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
}
创建对象

使用 @Builder 自动生成的 Builder 类来创建对象:

public class Main {
    public static void main(String[] args) {
        User user = User.builder()
                .name("John Doe")
                .age(30)
                .email("john.doe@example.com")
                .build();
        
        System.out.println(user);
    }
}

在上述示例中,User 类使用了 @Builder 注解,Lombok 自动为该类生成了一个内部静态的 UserBuilder 类。通过 User.builder() 方法可以获取这个 UserBuilder 对象,并通过链式调用的方式设置属性,最后调用 build() 方法创建 User 对象。

主要功能

  1. 链式调用:通过链式调用的方式设置属性值,代码更简洁明了。
  2. 可选参数:可以选择性地设置参数,未设置的参数将使用默认值。
  3. 不可变对象:可以轻松创建不可变对象,通过 Builder 模式创建的对象是线程安全的。

高级用法

自定义构建方法

你可以自定义构建方法以进行额外的初始化或验证:

@Builder
@ToString
public class User {
    private String name;
    private int age;
    private String email;
    
    public static class UserBuilder {
        public User build() {
            // 进行额外的初始化或验证
            if (this.age < 0) {
                throw new IllegalArgumentException("Age cannot be negative");
            }
            return new User(name, age, email);
        }
    }
}
使用 @Builder.Default

当使用 @Builder 时,默认值可能会被忽略。可以使用 @Builder.Default 注解来指定默认值:

@Builder
@ToString
public class User {
    private String name;
    private int age;
    @Builder.Default
    private String email = "default@example.com";
}

依赖配置

要使用 Lombok 的 @Builder 注解,需要在项目中添加 Lombok 依赖。以下是 Maven 和 Gradle 的依赖配置示例:

Maven
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>最新版本号</version>
    <scope>provided</scope>
</dependency>
Gradle
dependencies {
    compileOnly 'org.projectlombok:lombok:最新版本号'
    annotationProcessor 'org.projectlombok:lombok:最新版本号'
}

添加依赖后,需要在 IDE 中启用注解处理器,以便自动生成代码。

2. 常见的隐藏陷阱

陷阱一:无参构造函数缺失
当我们使用@Builder时,Lombok不会自动生成无参构造函数,这可能在某些情况下导致反射调用失败。

当你使用Lombok的@Builder注解时,它会自动生成一个静态的内部类,通常被称为Builder类,这个Builder类提供了一种构建对象的方法。但是,@Builder不会自动生成无参构造函数,这可能会导致在通过反射实例化类时出现问题。

而没有@Builder时,Java编译器会默认生成一个无参构造函数(如果没有定义任何构造函数),因此通过反射调用构造函数时不会报错。

解决方案
使用@NoArgsConstructor注解:

import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
public class User {
    private String name;
    private int age;
}

陷阱二:与其他注解的兼容性问题
某些注解与@Builder可能存在兼容性问题,例如@JsonCreator和Jackson库的使用。

解决方案
手动编写Builder类或结合@JsonPOJOBuilder注解:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@JsonDeserialize(builder = User.UserBuilder.class)
public class User {
    private String name;
    private int age;

    @JsonPOJOBuilder(withPrefix = "")
    public static class UserBuilder {
    }
}

陷阱三:继承问题
在继承体系中使用@Builder可能会导致父类的属性无法正确初始化。

解决方案
使用@SuperBuilder注解:

import lombok.Data;
import lombok.experimental.SuperBuilder;

@Data
@SuperBuilder
public class User {
    private String name;
    private int age;
}

@Data
@SuperBuilder
public class Employee extends User {
    private String position;
}

3. 实用的解决方案和最佳实践

最佳实践一:结合其他注解使用
为了避免无参构造函数问题,建议在使用@Builder时总是加上@NoArgsConstructor@AllArgsConstructor注解。

最佳实践二:自定义Builder
在需要特殊逻辑或与其他库集成时,可以手动编写Builder类,确保完全掌控构建过程。

最佳实践三:注重代码可读性
虽然@Builder提供了强大的功能,但在使用时应注意代码的可读性,避免过度复杂化。必要时,提供清晰的文档和注释。

知识点总结

  1. @Builder的基本原理:了解@Builder的工作机制,掌握其基本用法。
  2. 无参构造函数的缺失:认识到@Builder不会自动生成无参构造函数,并学习如何使用@NoArgsConstructor解决此问题。
  3. 与其他注解的兼容性:了解@Builder与其他注解(如@JsonCreator)的兼容性问题,掌握解决方案。
  4. 继承体系中的问题:理解在继承体系中使用@Builder的限制,学习如何使用@SuperBuilder解决相关问题。
  5. 最佳实践:掌握一系列最佳实践,确保在使用@Builder时既能享受其便利,又能避免常见陷阱。

通过这篇文章,希望读者能够深入理解@Builder的工作机制,避免掉进常见的陷阱,并在实际开发中更加高效地使用这个强大的工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/783220.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5改进系列(32)——替换主干网络之PKINet(CVPR2024 | 面向遥感旋转框主干,有效捕获不同尺度上的密集纹理特征)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2)——添加CBAM注意力机制 YOLOv5改进系列(3)——添加CA注意力机制 YOLOv5改进系列(4)——添加ECA注意力机制 YO…

21. Java AQS 原理

1. 前言 本节内容主要是对 AQS 原理的讲解&#xff0c;之所以需要了解 AQS 原理&#xff0c;是因为后续讲解的 ReentrantLock 是基于 AQS 原理的。本节内容相较于其他小节难度上会大一些&#xff0c;基础薄弱的学习者可以选择性学习本节内容或者跳过本节内容。 了解什么是 AQ…

从无计划到项目管理高手,只需避开这两大误区!

在项目管理的过程中&#xff0c;制定计划是不可或缺的一环。然而&#xff0c;在实践中&#xff0c;我们往往会遇到两种常见的误区&#xff0c;这些误区不仅阻碍了计划的有效实施&#xff0c;还可能让我们在追求目标的道路上迷失方向。 误区一&#xff1a;认为没有什么可计划的…

Nacos 国际化

项目需要&#xff0c;后端异常信息需要进行国际化处理。所有想有没有方便易用的可选项。 1、国际化配置调整&#xff0c;不需要重启系统 2、可支持添加不同或自定义语言包&#xff08;就是配置的资源文件&#xff09; 参考&#xff1a; Nacos实现SpringBoot国际化的增强_spr…

硅纪元视角 | Speak火了!3个月收入翻倍,OpenAI为何频频下注?

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

LabVIEW自动探头外观检测

开发了一套基于LabVIEW的软件系统&#xff0c;结合视觉检测技术&#xff0c;实现探头及连接器外观的自动检测。通过使用高分辨率工业相机、光源和机械手臂&#xff0c;系统能够自动定位并检测探头表面的细微缺陷&#xff0c;如划痕、残胶、异色、杂物等。系统支持多种探头形态&…

王老师 linux c++ 通信架构 笔记(二)

&#xff08;7&#xff09;本条目开始配置 linux 的固定 ip 地址&#xff0c;以作为服务器使用&#xff1a; 首先解释 linux 的网口编号&#xff1a; linux 命令 cd &#xff1a; change directory 改变目录。 ls &#xff1a; list 列出某目录下的文件 根目录文件名 / etc &a…

Kubernetes运维工程师必备:K8s 基础面试题精编(一)

Kubernetes运维工程师必备:K8s 基础面试题精编(一) 1. 什么是Kubernetes?2. Kubernetes如何实现容器编排?3. 说出k8s的常见资源对象?4. 什么是pod?5. Deployment介绍及使用?6. statefulesets介绍及使用?7. statefulesets和deployment区别?8. 什么是调度器(Scheduler…

三菱PLC 实现PID控制温度 手搓PID指令!!!

目录 1.前言 2.PID公式的讲解 3.程序 4.硬件介绍 5.EPLAN图纸 6.成果展示 7.结语 1.前言 新手想要学习PLC的PID控制 首先会被大串的PID 公式吓到 PID公式有很多种&#xff1a;基本PID 位置式 增量式 模拟式 理想型 等等 但是 不要急 别看这么多公式 其实 将公式拆…

知识图谱驱动的深度推理:ToG算法的创新与应用

LLMs通过预训练技术在大量文本语料库上生成连贯且符合上下文的响应。然而&#xff0c;面对需要复杂知识推理的任务时&#xff0c;它们存在明显的局限性。这些问题包括对超出预训练阶段的专业知识的准确回答失败&#xff0c;以及缺乏责任性、可解释性和透明度。为了解决这些问题…

(19)夹钳(用于送货)

文章目录 前言 1 常见的抓手参数 2 参数说明 前言 Copter 支持许多不同的抓取器&#xff0c;这对送货应用和落瓶很有用。 按照下面的链接&#xff08;或侧边栏&#xff09;&#xff0c;根据你的设置了解配置信息。 Electro Permanent Magnet v3 (EPMv3)Electro Permanent M…

教育相关知识

教育的含义 教育的基本要素 教育的属性 教育的功能 教育的起源 教育的发展

软件安全性测试的工具有哪些?

软件安全性测试是确保软件系统在设计和实施过程中能够保护系统的机密性、完整性和可用性。为了进行软件安全性测试&#xff0c;有许多工具可供选择&#xff0c;这些工具可以帮助测试人员发现潜在的安全漏洞和弱点&#xff0c;从而提高软件系统的安全性。 以下是一些常用的软件安…

两年经验前端带你重学前端框架必会的ajax+node.js+webpack+git等技术 Day2

前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;个人学习心得作业及bug记录 Day2 你好,我是Qiuner. 为帮助别人少走弯路和记录自己编程学习过程而写博客 这是我的 github https://github.com/Qiuner ⭐️ ​ gitee https://gitee.com/Qiuner &#x1f339; 如果本…

从RL的专业角度解惑 instruct GPT的目标函数

作为早期chatGPT背后的核心技术&#xff0c;instruct GPT一直被业界奉为里程碑式的著作。但是这篇论文关于RL的部分确写的非常模糊&#xff0c;几乎一笔带过。当我们去仔细审查它的目标函数的时候&#xff0c;心中不免有诸多困惑。特别是作者提到用PPO来做强化学习&#xff0c;…

Jenkins 常用的 Linux 指令

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

法国工程师IMT联盟 密码学及其应用 2022年期末考试

1 密码学 1.1 问题1 对称加密&#xff08;密钥加密) 1.1.1 问题 对称密钥la cryptographie symtrique和公开密钥有哪些优缺点&#xff1f; 1.1.1.1 对称加密&#xff08;密钥加密)的优缺点 1.1.1.1.1 优点 加解密速度快encrypt and decrypt&#xff1a;对称加密算法通常基于…

不锈钢焊条A022

说明&#xff1a;A022是钛钙型药皮的不锈钢焊条。交直流两用&#xff0c;操作性能良好。熔敷金属有良好的耐热、耐腐蚀及抗裂性能。 用途&#xff1a;用于焊接尿素、合成纤维等设备及相同类型的不锈钢结构&#xff0c;也可用于焊后不能进行热处理的铬不锈钢以及复合钢和异种钢等…

使用 pgbadger 自动填充准备好的语句占位符#PG培训

问题 当某些应用程序使用扩展查询协议/准备好的语句来查询 Postgres&#xff08;出于性能原因&#xff0c;您通常应该这样做&#xff09;并由于某种原因获得查询错误或只是超过“慢查询日志”阈值&#xff08;log_min_duration_statement配置参数&#xff09;时&#xff0c;您…

Kafka(二)Producer第一篇

一&#xff0c;Client开发 生产逻辑需要具备以下几个 步骤&#xff1a; &#xff08;1&#xff09;配置生产者客户端参数及创建相应的生产者实例。 &#xff08;2&#xff09;构建待发送的消息。 &#xff08;3&#xff09;发送消息。 &#xff08;4&#xff09;关闭生产者实例…