科普文:Lombok使用及工作原理详解
1. 概叙
Lombok是什么?
- Project Lombok 是一个 JAVA 库,它可以自动插入编辑器和构建工具,为您的 JAVA 锦上添花。
- 再也不要写另一个 getter/setter 或 equals 等方法,只要有一个注注解,你的类就有一个功能齐全的生成器,自动记录变量,等等。
官方地址:https://projectlombok.org/
Lombok是一种Java™实用工具,可用来帮助开发人员消除Java的冗长代码,尤其是对于简单的Java对象(POJO)。它通过注释实现这一目的。
首先Lombok是一款Java IDE的应用工具插件,一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,比如属性的构造器、getter、setter、equals、hashcode、toString方法。结合IDE,通过使用对应的注解,可以在编译源码的时候生成对应的方法。
通过在开发环境中实现Lombok,开发人员可以节省构建诸如hashCode()和equals()这样的方法以及以往用来分类各种accessor和mutator的大量时间。
虽然上述的那些常用方法IDE都能生成,但是lombok更加简洁与方便,能够达到的效果就是在源码中不需要写一些通用的方法,但是在编译生成的字节码文件中会帮我们生成这些方法,这就是lombok的神奇作用。
lombok插件安装
使用的IDE是Intellij idea,编译器需要在
preference->plugins->Browse repositories
搜索lombok,然后安装plugins,需要稍等片刻
添加jar包
在项目中添加lombok的jar包,笔者用的是maven,所以在pom文件中添加了如下的依赖。gradle使用见官网。
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.16</version><scope>provided</scope>
</dependency>
常用的注解
官网注解介绍:Stable

2. Lombok原理介绍
2.1 Java类文件编译过程
首先,我们知道 Lombok 功能是作用在类编译时期,那我们来看下一个类编译的过程。
- 定义一个 PersonDTO.Java 类
代码语言:javascript
复制
public class PersonDTO {//姓名private String name;
}
- Javac PersonDTO.Java 对源代码进行解析转化,会生成一棵抽象语法树( AST );
- 运行过程中会调用实现了 JSR 269 注解处理器,下面介绍;
- JSR 实现可处理自定义逻辑,包括可修改编译后的抽象语法树(AST);
- Javac 使用修改后的抽象语法树(AST)生成字节码文件;
过程如下图:

AST 是抽象语法树(Abstract Syntax Tree) 的缩写,是 JAVA 源代码展示的一种树状结构它将代码的结构和语法元素映射到树节点上,使得程序可以在编译、
分析和转换过程中更容易地操作和理解。有兴趣可以学习 JavaParser 源码, 了解将 Java 源代码解析生成成一个抽象语法树( AST ),这个树形结构表示了代码的
语法结构包括类、方法、变量、语句等等过程。
github地址:https://github.com/javaparser/javaparser.
如: PersonDTO.Java 在 idea 中使用可视化工具展示文件 AST 树

2.2 JSR 269介绍
首先 JSR 269全称" Pluggable Annotation Processing API ",是 JAVA 平台的一项规范,也被称之为注解处理器 API 。在Java6引入,用于在编译时处理
注解,目标是提供更丰富的编译时元数据处理能力,以增强Java编译器的功能。这个规范允许开发人员创建自定义的注解处理器,这些处理器可以在编译时检查、分析和生成Java代码。
JSR 269在JDK6中被引入,作为APT的替代方案。javac执行的时候会调用Pluggable Annotation Processing API,因此我们可以通过实现此API来改变编译期的一些行为从而达到目的。具体的编译流程如下:

javac编译流程
举例来说,现在有一个实现了Pluggable Annotation Processing API的程序A,那么使用javac编译时的具体流程如下:
1. javac编译器对源码进行分析,生成一个抽象的语法树(AST)
2. javac编译器运行A程序
3. A程序完成逻辑,一般是修改此语法树
4. javac使用修改后的语法树生成可执行的字节码文件
Lomok便是通过Pluggable Annotation Processing API来实现代码生成的。
应用框架:
- Servlet、JAX-RS(RESTful Web服务)JSR 269 来生成用于处理 HTTP 请求的代码。
- Spring Boot 项目中以处理各种自定义注解,如 @Controller、@Service、@Repository 等。这些注解可以用于自动化配置、依赖注入等方面。
- Hibernate 它使用 JSR 269 来处理 JPA 注解,并生成与数据库交互的代码。
- Lombok 是一个 JAVA 库,它通过注解处理器生成常见的 JAVA 代码,如 getter、setter、equals、hashCode 等,以简化开发工作。
- MapStruct 是一个用于对象映射的 JAVA 库,它使用 JSR 269 来生成类型安全的映射代码,帮助开发人员将一个对象映射到另一个对象。
如何实现自定义注解注解处理器:
1.声明自定义注解;如 Lombok 下的 @Data,@Getter,@Setter等。
2.实现 Process接口,或者继承 AbstractProcessor 复写 process 方法,处理自定义注解逻辑。
代码语言:javascript
复制
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import java.util.Set;@SupportedAnnotationTypes("com.example.MyAnnotation") // 自定义注解
@SupportedSourceVersion(SourceVersion.RELEASE_8) //支持的Java版本
public class MyAnnotationProcessor extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 在这里处理自定义注解,生成代码或执行其他任务return true;}
}
3.注册注解处理器
两种方式:
- Resource 文件:项目 META-INF/services 创建 javax.annotation.processing.Processor 文件,自定义注解处理器的全类名写到此文件中。
- 通过谷歌工具包 auto-service ,可自动生成以上配置文件。
代码语言:javascript
复制
<!-- 编译注解执行注册 jar包-->
<dependency><groupId>com.google.auto.service</groupId><artifactId>auto-service</artifactId><version>1.0.1</version>
</dependency> @AutoService(Processor.class) //谷歌工具包方式:注册注解处理器
@SupportedAnnotationTypes("com.example.MyAnnotation") // 自定义注解
@SupportedSourceVersion(SourceVersion.RELEASE_8) //支持的Java版本
public class MyAnnotationProcessor extends AbstractProcessor {@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 在这里处理自定义注解,生成代码或执行其他任务return true;}
}
2.3 Lombok 实现原理
1. Lombok 实际就是结合注解处理器和 AST 技术, Lombok 实现的注解处理器会遍历 AST ,查找与 Lombok 注解相关的元素,根据注解的要求生成新的代码。

2.编译前后的 AST 语法树对比

加入@Getter注解编译后

3. Lombok 注解处理器,采用 Resource 方式注册编译注解处理器

注解处理器 AnnotationProcessor 源码:
代码语言:javascript
复制
class AnnotationProcessorHider {public static class AstModificationNotifierData {public volatile static boolean lombokInvoked = false;}public static class AnnotationProcessor extends AbstractProcessor {// 获取支持的注解类型@Overridepublic Set<String> getSupportedOptions() {return instance.getSupportedOptions();}// 获取支持的注解类型@Overridepublic Set<String> getSupportedAnnotationTypes() {return instance.getSupportedAnnotationTypes();}// 支持的JDK版本@Overridepublic SourceVersion getSupportedSourceVersion() {return instance.getSupportedSourceVersion();}//初始化环境@Overridepublic void init(ProcessingEnvironment processingEnv) {disableJava9SillyWarning();AstModificationNotifierData.lombokInvoked = true;instance.init(processingEnv);super.init(processingEnv);}// 处理自定义注解逻辑@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {return instance.process(annotations, roundEnv);}}
自定义注解处理器 Handler : 在 Jar 包的 lombok.javac.handlers下,每个注解处理对应一个 Handler. 如 HadlerGetter.java 操作 AST 树生成 getter 方法.

2.4手动实现一个 @Getter 功能
2.4.1.创建 maven 工程 demo 包含两个子模块 getter/getter-use

2.4.2. getter 工程
pom文件:
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>demo</artifactId><groupId>com.example</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>getter</artifactId><dependencies><!-- 注解执行器依赖jar --><dependency><groupId>com.sun</groupId><artifactId>tools</artifactId><version>1.6.0</version><scope>system</scope><systemPath>${java.home}/../lib/tools.jar</systemPath></dependency><!-- 编译注解执行注册 --><dependency><groupId>com.google.auto.service</groupId><artifactId>auto-service</artifactId><version>1.0.1</version></dependency></dependencies>
</project>
自定义 GetterTest 注解
代码语言:javascript
复制
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @author zcy1*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface GetterTest {
}
GetterTest 编译注解处理器 GetterProcessor
代码语言:javascript
复制
import com.google.auto.service.AutoService;
import com.sun.source.tree.Tree;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeTranslator;
import com.sun.tools.javac.util.*;import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import java.util.Set;/*** @author zcy1*/
@AutoService(Processor.class) //谷歌工具包方式:注册注解处理器
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("GetterTest")
public class GetterProcessor extends AbstractProcessor {/*** 用于在编译器打印消息的组件*/private Messager messager;/*** 提供待处理抽象语法树*/private JavacTrees trees;/*** 用来构造语法树节点*/private TreeMaker treeMaker;/*** 用于创建标识符的对象*/private Names names;/*** 获取一些注解处理器执行处理逻辑时一些关键对象* @param processingEnv 处理环境*/@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) {super.init(processingEnv);this.messager = processingEnv.getMessager();this.trees = JavacTrees.instance(processingEnv);Context context = ((JavacProcessingEnvironment) processingEnv).getContext();this.treeMaker = TreeMaker.instance(context);this.names = Names.instance(context);}@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {// 获取自定义GetterTest注解的类Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(GetterTest.class);elementsAnnotatedWith.forEach(e -> {JCTree tree = trees.getTree(e);tree.accept(new TreeTranslator() {@Overridepublic void visitClassDef(JCTree.JCClassDecl jcClassDecl) {List<JCTree.JCVariableDecl> jcVariableDeclList = List.nil();// 在抽象树中找出所有的成员变量for (JCTree jcTree : jcClassDecl.defs) {if (jcTree.getKind().equals(Tree.Kind.VARIABLE)) {JCTree.JCVariableDecl jcVariableDecl = (JCTree.JCVariableDecl) jcTree;jcVariableDeclList = jcVariableDeclList.append(jcVariableDecl);}}// 对于变量进行生成getter方法的操作jcVariableDeclList.forEach(jcVariableDecl -> {messager.printMessage(Diagnostic.Kind.NOTE, jcVariableDecl.getName() + " has been processed");jcClassDecl.defs = jcClassDecl.defs.prepend(createGetterMethod(jcVariableDecl));});super.visitClassDef(jcClassDecl);}});});return true;}private JCTree.JCMethodDecl createGetterMethod(JCTree.JCVariableDecl jcVariableDecl) {ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();// 生成表达式 this.name = nameJCTree.JCExpressionStatement aThis = makeAssignment(treeMaker.Select(treeMaker.Ident(names.fromString("this")), jcVariableDecl.getName()), treeMaker.Ident(jcVariableDecl.getName())); statements.append(aThis);JCTree.JCBlock block = treeMaker.Block(0, statements.toList());// 生成入参 (String name)JCTree.JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(Flags.PARAMETER),jcVariableDecl.getName(), jcVariableDecl.vartype, null);List<JCTree.JCVariableDecl> parameters = List.of(param);// 生成返回对象 voidJCTree.JCExpression methodType = treeMaker.Type(new Type.JCVoidType());//生成方法名 getNameName methodName = getMethodName(jcVariableDecl.getName());// 返回语法树对象return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC),methodName, methodType, List.nil(),parameters, List.nil(), block, null);}/*** 驼峰方法名*/private Name getMethodName(Name name) {String s = name.toString();return names.fromString("get" + s.substring(0, 1).toUpperCase() + s.substring(1, name.length()));}private JCTree.JCExpressionStatement makeAssignment(JCTree.JCExpression lhs, JCTree.JCExpression rhs) {return treeMaker.Exec(treeMaker.Assign(lhs, rhs));}
}
2.4.4 getter-use工程
pom 文件 引入getter工程
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>demo</artifactId><groupId>com.example</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>getter-use</artifactId><dependencies><dependency><groupId>com.example</groupId><artifactId>getter</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies>
</project>
PersonDTO 使用@GetterTest
代码语言:javascript
复制
@GetterTest
public class PersonDTO {private String name;private Integer age;
}
2.5.5 项目进行编译
getter 模块下自动生成注册器

getter-use 模块下 PersonDTO.class 可见生成了对应属性的 get 方法

3.总结
本文通过以上对 Lombok 相关介绍,通过对 JAVA 文件编译过程分析和 JSR269 实现的方式, 基于这个规范然后引申出 Lombok 实现原理过程介绍,以及手动实现 getter 案例,想必我们对 Lombok 原理也有了相应的了解。虽然 Lombok 提供了许多便利,由于生成的代码不在源文件中可见,就会导致代码的可读性和维护性较差。在工作中 Lombok 使用时注意闭坑:
| 问题 | 解决 |
|---|---|
| @Data 和 @Builder 一起使用时,无参构造方法会被干掉 | 手动加上注解: @AllArgsConstructor、@NoArgsConstructor。 |
| @Builder 导致类属性默认值无效。 | 有默认值属性上加注解 : @lombok.Builder.Default。 |
| @Data 生成的 toString 方法,默认能不输出父类属性 | 子类添加: @ToString(callSuper = true)。 |
参考文献
Lombok 官网地址: https://projectlombok.org
JavaParser 源码地址: https://github.com/javaparser/javaparser
JAVA 抽象语法树 AST 浅析与使用: https://www.freesion.com/article/4068581927/
相关文章:
科普文:Lombok使用及工作原理详解
1. 概叙 Lombok是什么? Project Lombok 是一个 JAVA 库,它可以自动插入编辑器和构建工具,为您的 JAVA 锦上添花。再也不要写另一个 getter/setter 或 equals 等方法,只要有一个注注解,你的类就有一个功能齐全的生成器…...
飞致云开源社区月度动态报告(2024年7月)
自2023年6月起,中国领先的开源软件公司FIT2CLOUD飞致云以月度为单位发布《飞致云开源社区月度动态报告》,旨在向广大社区用户同步飞致云旗下系列开源软件的发展情况,以及当月主要的产品新版本发布、社区运营成果等相关信息。 飞致云开源大屏…...
mybatis-plus——实现动态字段排序,根据实体获取字段映射数据库的具体字段
前言 前端需要根据表头的点击控件可以排序,虽然前端能根据当前页的数据进行对应字段的排序,但也仅局限于实现当前页的排序,无法满足全部数据的排序,所以需要走接口的查询进行排序,获取最全的排序数据 实现方案 前端…...
redis:Linux安装redis,redis常用的数据类型及相关命令
1. 什么是NoSQL nosql[not only sql]不仅仅是sql。所有非关系型数据库的统称。除去关系型数据库之外的都是非关系数据库。 1.1为什么使用NoSQL NoSQL数据库相较于传统关系型数据库具有灵活性、可扩展性和高性能等优势,适合处理非结构化和半结构化数据,…...
JavaScript 和 HTML5 Canvas实现图像绘制与处理
前言 JavaScript 和 HTML5 的 canvas 元素提供了强大的图形和图像处理功能,使得开发者能够在网页上创建动态和交互式的视觉体验。这里我们将探讨如何使用 canvas 和 JavaScript 来处理图像加载,并在其上进行图像绘制。我们将实现一个简单的示例…...
Java之Java基础二十(集合[上])
Java 集合框架可以分为两条大的支线: ①、Collection,主要由 List、Set、Queue 组成: List 代表有序、可重复的集合,典型代表就是封装了动态数组的 ArrayList 和封装了链表的 LinkedList;Set 代表无序、不可重复的集…...
【C++BFS】1162. 地图分析
本文涉及知识点 CBFS算法 LeetCode1162. 地图分析 你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地。 请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距…...
实战:安装ElasticSearch 和常用操作命令
概叙 科普文:深入理解ElasticSearch体系结构-CSDN博客 Elasticsearch各版本比较 ElasticSearch 单点安装 1 创建普通用户 #1 创建普通用户名,密码 [roothlink1 lyz]# useradd lyz [roothlink1 lyz]# passwd lyz#2 然后 关闭xshell 重新登录 ip 地址…...
React-Native 宝藏库大揭秘:精选开源项目与实战代码解析
1. 引言 1.1 React-Native 简介 React-Native 是由 Facebook 开发的一个开源框架,它允许开发者使用 JavaScript 和 React 的编程模型来构建跨平台的移动应用。React-Native 的核心理念是“Learn Once, Write Anywhere”,即学习一次 React 的编程模型&am…...
数据结构:二叉树(链式结构)
文章目录 1. 二叉树的链式结构2. 二叉树的创建和实现相关功能2.1 创建二叉树2.2 二叉树的前,中,后序遍历2.2.1 前序遍历2.2.2 中序遍历2.2.3 后序遍历 2.3 二叉树节点个数2.4 二叉树叶子结点个数2.5 二叉树第k层结点个数2.6 二叉树的深度/高度2.7 二叉树…...
召唤生命,阻止轻生——《生命门外》
本书的目的,就是阻止自杀!拉回那些深陷在这样的思维当中正在挣扎犹豫的人,提醒他们珍爱生命,让更多的人,尤其是年轻人从执迷不悟的犹豫徘徊中幡然醒悟,回归正常的生活。 网络上抱孩子跳桥轻生的母亲&#…...
JVM:栈上的数据存储
文章目录 一、Java虚拟机中的基本数据类型 一、Java虚拟机中的基本数据类型 在Java中有8大基本数据类型: 这里的内存占用,指的是堆上或者数组中内存分配的空间大小,栈上的实现更加复杂。 Java中的8大数据类型在虚拟机中的实现:…...
C#实战 - C#实现发送邮件的三种方法
作者:逍遥Sean 简介:一个主修Java的Web网站\游戏服务器后端开发者 主页:https://blog.csdn.net/Ureliable 觉得博主文章不错的话,可以三连支持一下~ 如有疑问和建议,请私信或评论留言! 前言 当使用 C# 编程…...
数模原理精解【5】
文章目录 二元分布满足要求边际分布条件概率例子1例子2 损失函数概率分布期望值例 参考文献 二元分布 满足要求 连续情况下, φ ( x , y ) \varphi (x,y) φ(x,y)为随机变量 X 、 Y X、Y X、Y的联合概率分布(二元分布),如果以下条件满足: …...
C语言篇——使用运算符将16进制数据反转
比如:将一个16进制0xFD,即11111101,反向,输出10111111,即0xBF。 #include <stdio.h>unsigned char reverseBits(unsigned char num) {unsigned char reverse_num 0;int i;for (i 0; i < 8; i) {if ((num &…...
2025年和2024CFA一级SchweserKaplan Notes 全集 (内附分享链接)
CFA一级notes百度网盘下载 2024年和2025年 CFA一级考纲已经正式发布,相比与老考纲,新考纲变化实在不算小。 2024年和2025年 CFA一级notes完整版全 https://drive.uc.cn/s/6394c0b6b1a54?public1 2024年和2025年 cfa二级notes完整版全 https://driv…...
B树的实现:代码示例与解析
B树的实现:代码示例与解析 引言 B树是一种自平衡的树数据结构,广泛应用于文件系统和数据库系统中。它是一种多路搜索树,旨在保持数据有序并允许高效的查找、插入和删除操作。本文将深入探讨B树的实现,提供完整的代码示例和详细的…...
HCIA总结
一、情景再现:ISP网络为学校提供了DNS服务,所以,DNS服务器驻留在ISP网络内,而不再学校网络内。DHCP服务器运行在学校网络的路由器上 小明拿了一台电脑,通过网线,接入到校园网内部。其目的是为了访问谷歌网站…...
软件测试_接口测试面试题
接口测试是软件测试中的重要环节,它主要验证系统不同模块之间的通信和数据交互是否正常。在软件开发过程中,各个模块之间的接口是实现功能的关键要素,因此对接口进行全面而准确的测试是确保系统稳定性和可靠性的关键步骤。 接口测试的核心目…...
C++初阶学习第五弹——类与对象(下)
类与对象(上):C初阶学习第三弹——类与对象(上)-CSDN博客 类和对象(中):C初阶学习第四弹——类与对象(中)-CSDN博客 一.赋值运算符重载 1.1 运算符重载 C为…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
深入浅出Diffusion模型:从原理到实践的全方位教程
I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
