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

news2024/9/21 12:27:10

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


在这里插入图片描述

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

🏠 :小破站

@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的工作机制,避免掉进常见的陷阱,并在实际开发中更加高效地使用这个强大的工具。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java——面试题

1、JDK 和 JRE 有什么区别&#xff1f; JDK&#xff08;Java Development Kit&#xff09;&#xff0c;Java开发工具包 JRE&#xff08;Java Runtime Environment&#xff09;&#xff0c;Java运行环境 JDK中包含JRE&#xff0c;JDK中有一个名为jre的目录&#xff0c;里面包含…

电子发票管理系统-计算机毕业设计源码99719

摘 要 本文旨在设计和实现一个基于SpringBoot的电子发票管理系统&#xff0c;以提升企业的发票管理效率和准确性。随着电子化发票管理的需求增加&#xff0c;企业需要一个高效、可靠且功能丰富的系统来帮助管理发票信息。基于SpringBoot的电子发票管理系统将提供诸如发票信息、…

多数据源及其连接池的配置、事务管理器的注册和使用

&#xff08;ps&#xff1a;如果只有这几个数据源&#xff0c;请选择一个默认的数据源和对应的事务管理器均加上Primary注解&#xff09;示例&#xff1a; 1.在yml文件中配置多数据源/池的信息 spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:initia…

nodejs + vue3 模拟 fetchEventSouce进行sse流式请求

先上效果图: 前言: 在GPT爆发的时候,各项目都想给自己的产品加上AI,蹭上AI的风口,因此在最近的一个需求,就想要给项目加入Ai的功能,原本要求的效果是,查询到对应的数据后,完全展示出来,也就是常规的post请求,后来这种效果遇到了一个很现实的问题:长时间的等待。我…

SCI三区|儿童学习优化算法KLO:基于社会进化和认知学习的优化算法

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;ST Javed受到社会环境下家庭儿童的早期社会学习行为启发&#xff0c;提出了儿童学习优化算法&#xff08;Kids Learning Optimizer, KLO&#xff09;。 2.算法原理 2.…

使用MySQLInstaller配置MySQL

操作步骤 1.配置High Availability 默认选项Standalone MySQL Server classic MySQL Replication 2.配置Type and Networking ◆端口默认启用TCP/P网络 ◆端口默认为3306 3.配置Account and Roles 设置root账户的密码、添加其他管理员 4.配置Windows Service ◆配置MySQL Serv…

day4单向链表

主程序 #include "fun.h" int main(int argc, const char *argv[]) { node_p Lcreate_head();//创建链表 printf("########################链表的头插尾插\n"); insert_head(L,45);//头插 insert_head(L,45); insert_tail(L,45);/…

imx6ull/linux应用编程学习(14) MQTT基础知识

什么是mqtt&#xff1f; 与HTTP 协议一样&#xff0c; MQTT 协议也是应用层协议&#xff0c;工作在 TCP/IP 四层模型中的最上层&#xff08;应用层&#xff09;&#xff0c;构建于 TCP/IP协议上。 MQTT 最大优点在于&#xff0c;可以以极少的代码和有限的带宽&#xff0c;为连接…

极客时间:使用Autogen Builder和本地LLM(Microsoft Phi3模型)在Mac上创建本地AI代理

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

Jenkins教程-15-常用插件-Blue Ocean

上一小节我们学习了Jenkins定时任务构建的方法&#xff0c;本小节我们讲解一下Jenkins常用插件Blue Ocean的使用方法。 Blue Ocean 提供了一套可视化操作界面来帮助创建、编辑 Pipeline 任务。 Blue Ocean 特性&#xff1a; 流水线编辑器&#xff1a;用于创建贯穿始终的持续交…

JavaScript学习笔记(七)

45.9 JavaScript 可迭代对象 可迭代对象&#xff08;Iterables&#xff09;是可以使用 for..of 进行迭代的对象。 从技术上讲&#xff0c;可迭代对象必须实现 Symbol.iterator 方法。 45.9.1 遍历字符串 <body><p id"demo"></p><script>c…

关于centos7自带的nginx1.20.1开启https后,XP系统的IE6和IE8无法显示网页的问题

CentOS7自带的nginx-1.20.1是支持HTTP/2和TLS1.3的。 软件包名称&#xff1a;nginx-1.20.1-10.el7.x86_64 CentOS7默认开启了HTTP/2&#xff0c;但没有开启TLS1.3&#xff0c;以及IE6和IE8的https访问。 开启方法&#xff1a; ssl_ciphers HIGH:!aNULL:!MD5;改为ssl_ciphers…

1-3分钟爆款视频素材在哪找啊?这9个热门爆款素材网站分享给你

在如今快节奏的时代&#xff0c;短视频已成为吸引观众注意力的黄金手段。然而&#xff0c;要制作出1-3分钟的爆款视频&#xff0c;除了创意和剪辑技巧外&#xff0c;选择合适的素材至关重要。那么&#xff0c;哪里可以找到那些能让你的视频脱颖而出的爆款素材呢&#xff1f;不用…

【UE5.1】Chaos物理系统基础——05 蓝图绑定Chaos破裂或碰撞事件

步骤 1. 新建一个父类为Actor的蓝图&#xff0c;这里命名为“BP_ChaosExplosionEvent” 打开“BP_ChaosExplosionEvent”&#xff0c;添加一个变量&#xff0c;这里命名为“GC”&#xff0c;变量类型为“几何体集actor”&#xff0c;设置为可编辑实例 在事件图表中添加如下节点…

ELK+Filebeat+Kafka+Zookeeper

本实验基于ELFK已经搭好的情况下 ELK日志分析 架构解析 第一层、数据采集层 数据采集层位于最左边的业务服务器集群上&#xff0c;在每个业务服务器上面安装了filebeat做日志收集&#xff0c;然后把采集到的原始日志发送到Kafkazookeeper集群上。第二层、消息队列层 原始日志发…

通过端口转发实现docker容器运行时端口更改

通过端口转发实现docker容器运行时端口更改 前言启动容器查看容器ip地址端口转发 前言 关于修改docker正在运行中容器端口&#xff0c;网上大部分分为3类: 1. 删除原有容器重新创建;2. 改配置文件;3. 在现有容器上新提交镜像&#xff0c;用新镜像起新的容器。 1和3属于同一种流…

Matlab手搓线性回归-非正规方程法

原理&#xff1a;wxb&#xff0c;x是输入&#xff0c;求得的结果与真实值y求均方误差。 采用链式法则求导 参数更新&#xff0c;梯度下降法&#xff08;批量梯度下降&#xff09; 随机生成数据&#xff1a; m100&#xff1b;生成100个数据&#xff0c;并添加随机噪声 clear; …

9、Python之文本解析:字符串格式化的逆操作?

引言 前面的文章中&#xff0c;提到了关于Python中字符串中的相关操作&#xff0c;更多地涉及到了字符串的格式化&#xff0c;有些地方也称为字符串插值操作&#xff0c;本质上&#xff0c;就是把多个字符串拼接在一起&#xff0c;以固定的格式呈现。 关于字符串的操作&#…

2021版本的idea热部署的详细步骤

背景&#xff1a;我是自己用的是2021版本的idea,然后发现跟2023版本的热部署不太一样&#xff0c;所以&#xff0c;今天自己出一期这样的文章吧&#xff01;&#xff01;&#xff01;其他人配置的时候根据自己的情况&#xff0c;来阅读吧&#xff01; 第一步&#xff1a;方式一…

光伏项目开发合作模式

光伏项目开发合作模式多种多样&#xff0c;根据应用场景的不同&#xff0c;主要分为户用光伏项目合作模式和工商业光伏项目合作模式。本文将分别介绍这两种模式的特点和常见形式&#xff0c;帮助大家更好地了解光伏项目开发的市场运作。 一、户用光伏项目合作模式 1.用户全款购…