视讯游戏提供最新游戏下载和手游攻略!

Lombok介绍、使用及总结

发布时间:2024-09-05浏览:98

大家好,今天小编来为大家解答Lombok介绍、使用及总结这个问题,很多人还不知道,现在让我们一起来看看吧!

1 Lombok背景介绍

官方介绍如下:

Lombok 项目通过添加知道如何构建和编译简单、无样板、不完全是Java 代码的“处理程序”,使Java 成为一种更有趣的语言。

大致意思是Lombok可以通过添加一些“处理程序”来让Java变得更简单、更快。

2 如何使用龙目岛

Lombok可以通过简单注解的形式简化Java代码,提高开发人员的开发效率。比如开发中经常需要编写的Javabean,需要时间添加相应的getter/setter,还可能需要编写构造函数、equals等方法,并且需要维护。当属性较多时,就会出现大量的getter/setter方法。看起来很长,没有太多技术含量。一旦修改了属性,很容易犯忘记修改相应方法的错误。

Lombok 可以通过注解在编译时自动为属性生成构造函数、getter/setter、equals、hashcode 和toString 方法。神奇的是,源代码中没有getter 和setter 方法,但编译后的字节码文件中却有getter 和setter 方法。这省去了你手动重建这些代码的麻烦,并且让代码看起来更干净。

Lombok的使用和引用jar包是一样的。可以从官网(https://projectlombok.org/download)下载jar包,或者使用maven添加依赖:

org.projectlomboklombok1.16.20提供

接下来我们来分析一下Lombok中注解的具体用法。

2.1 @数据

类上的@Data注解会自动为该类的所有属性生成setter/getter、equals、canEqual、hashCode和toString方法。如果是final属性,则不会为该属性生成setter方法。

官方给出的例子如下:

导入lombok.AccessLevel;导入lombok.Setter;导入lombok.Data;导入lombok.ToString;@Data 公共类DataExample { 私有最终字符串名称; @Setter(AccessLevel.PACKAGE) 私有int 年龄;私人双分;私有String[] 标签; @ToString(includeFieldNames=true) @Data(staticConstructor='of') 公共静态类练习{ 私有最终字符串名称;私人最终T 值; }}

如果不使用Lombok,实现如下:

导入java.util.Arrays;公共类DataExample { 私有最终字符串名称;私有整数年龄;私人双分;私有String[] 标签;公共DataExample(String name) { this.name=name; } public String getName() { return this.name; } } 无效setAge(int 年龄) { this.age=年龄; } public int getAge() { return this.age; } } public void setScore(double Score) { this.score=分数; } public double getScore () { return this.score; } } public String[] getTags() { return this.tags; } } public void setTags(String[] Tags) { this.tags=标签; } @Override public String toString() { return ' DataExample(' + this.getName() + ', ' + this.getAge() + ', ' + this.getScore() + ', ' + Arrays.deepToString(this .getTags()) + ')'; } protected boolean canEqual(Object other) { return other实例的DataExample; } @Override public boolean equals(Object o) { if (o==this) return true; } if (!(o instanceof DataExample)) 返回false;数据示例其他=( 数据示例) o; if (!other.canEqual((Object)this)) 返回false; if (this.getName()==null ? other.getName() !=null :this.getName().equals(other .getName())) 返回false; if (this.getAge() !=other.getAge()) 返回false; if (Double.compare(this.getScore(), other.getScore()) !=0) 返回false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) 返回false;返回真; } @Override public int hashCode() { 最终int PRIME=59;整数结果=1;最终长temp1=Double.doubleToLongBits(this.getScore());结果=(结果*PRIME) + (this.getName()==null ? 43 : this.getName().hashCode());结果=(结果*PRIME) + this.getAge();结果=(结果*PRIME) + (int)(temp1 ^ (temp1 32));结果=(结果*PRIME) + Arrays.deepHashCode(this.getTags());返回结果; } 公共静态类练习{ 私有最终字符串名称;私人最终T 值;私人练习(字符串名称,T值){ this.name=name; this.value=值; } public staticExerciseof(String name, T value) { return newExercise(name, value); } public String getName() { return this.name; } } public T getValue() { return this.value; } } @Override public String toString() { return 'Exercise(name=' + this .getName() + ', value=' + this.getValue() + ')'; } protected boolean canEqual(Object other) { return other instanceof 练习; } @Override public boolean equals(Object o) { if (o==this) return true; } if (!(o instanceof 练习)) 返回false;锻炼?其他=(锻炼?)o; if (!other.canEqual((Object)this)) 返回false; if (this.getName()==null ? other.getValue() !=null :this.getName().equals(other.getName())) 返回false; if (this.getValue()==null ? other.getValue() !=null :this.getValue().equals(other.getValue())) 返回false;返回真; } @Override public int hashCode() { 最终int PRIME=59;整数结果=1;结果=(结果* PRIME) + (this.getName()==null ? 43 : this.getName().hashCode());结果=(结果*PRIME) + (this.getValue()==null ? 43 : this.getValue( ).hashCode());返回结果; } }}

2.2 @Getter/@Setter

如果你觉得@Data太残酷了(因为@Data集成了@ToString、@EqualsAndHashCode、@Getter/@Setter和@RequiredArgsConstructor的所有功能),你可以使用@Getter/@Setter注解。该注释位于属性上。会自动为相应的属性生成Getter/Setter 方法。示例如下:

导入lombok.AccessLevel;导入lombok.Getter;导入lombok.Setter;公共类GetterSetterExample { @Getter @Setter private intage=10; @Setter(AccessLevel.PROTECTED) 私有字符串名称; @Override public String toString() { return String .format('%s (age: %d)', 姓名, 年龄); }}

如果不使用龙目岛:

公共类GetterSetterExample { 私有int 年龄=10;私有字符串名称; @Override public String toString() { return String.format('%s (age: %d)', 姓名, 年龄); } public int getAge() { 返回年龄; } 公共无效setAge(int 年龄) { this.age=年龄; } protected void setName(String name) { this.name=name; }}

2.3 @非空

示例如下:

导入lombok.NonNull;公共类NonNullExample 扩展了Something { 私有字符串名称;公共NonNullExample(@NonNull Person person) { super('Hello'); this.name=person.getName(); }}

不使用龙目岛:

导入lombok.NonNull;公共类NonNullExample 扩展了Something { 私有字符串名称;公共NonNullExample(@NonNull Person person) { super('Hello'); if (person==null) { throw new NullPointerException('person'); }这个.name=person.getName(); }}

2.4 @清理

这个注解可以帮助我们自动调用close()方法,大大简化了代码。

示例如下:

导入lombok.Cleanup;导入java.io.*;public class CleanupExample { public static void main(String[] args) throws IOException { @Cleanup InputStream in=new FileInputStream(args[0]); } @Cleanup OutputStream out=new FileOutputStream(args[1]); byte[] b=新字节[10000]; while (true) { int r=in.read(b); if (r==-1) 中断; out.write(b, 0 , r); } }}

如果不使用Lombok,则需要以下内容:

导入java.io.*;public class CleanupExample { public static void main(String[] args) throws IOException { InputStream in=new FileInputStream(args[0]); }尝试{ OutputStream out=new FileOutputStream(args[1]);尝试{ byte[] b=新字节[10000]; while (true) { int r=in.read(b); if (r==-1) 中断;输出.write(b, 0, r); } } 最后{ if (out !=null) { out.close(); } } } 最后{ if (in !=null) { in.close(); } } }}

2.5 @EqualsAndHashCode

默认情况下,所有非静态和非瞬态属性都用于生成equals 和hasCode。还可以通过排除注释排除某些属性。

示例如下:

导入lombok.EqualsAndHashCode;@EqualsAndHashCode(exclude={'id', 'shape'})public class EqualsAndHashCodeExample { 私有瞬态inttransientVar=10;私有字符串名称;私人双分; private Shape 形状=new Square(5, 10) ;私有String[] 标签;私有int id;公共字符串getName() { 返回this.name; } @EqualsAndHashCode(callSuper=true) public static class Square extends Shape { private final int width, height; } public Square(int width, int height) { this.width=width; } this.height=高度; } }}

2.6 @ToString

该类用@ToString注释,Lombok将生成一个toString()方法。默认情况下,将输出类名和所有属性(按照属性定义的顺序),以逗号分隔。

通过将includeFieldNames 参数设置为true,可以显式输出toString() 属性。这是不是有点绕?通过代码来看就更清楚了。

使用龙目岛的示例:

导入lombok.ToString;@ToString(exclude='id')public class ToStringExample { private static final int STATIC_VAR=10;私有字符串名称; private Shape 形状=new Square(5, 10);私有String[] 标签;私有int id;公共字符串getName() { return this.getName(); } @ToString(callSuper=true, includeFieldNames=true) public static class Square extends Shape { private Final int width, height; } public Square(int width, int height) { this.width=width; } this.height=高度; } }}

不使用Lombok的示例如下:

导入java.util.Arrays;公共类ToStringExample { 私有静态最终int STATIC_VAR=10;私有字符串名称; private Shape 形状=new Square(5, 10);私有String[] 标签;私有int id;公共字符串getName() { return this.getName(); } public static class Square extends Shape { private Final int width, height; public Square(int width, int height) { this.width=width; } this.height=高度; } @Override public String toString() { return 'Square(super=' + super.toString() + ', width=' + this.width + ', height=' + this.height + ')'; @Override public String toString() { return 'ToStringExample(' + this.getName() + ', ' + this.shape + ', ' + Arrays.deepToString(this.tags) + ')'; }}

2.7 @NoArgsConstructor、@RequiredArgsConstructor 和@AllArgsConstructor

无参数构造函数、部分参数构造函数、全参数构造函数。 Lombok 无法实现多参数构造函数的重载。

Lombok示例代码如下:

导入lombok.AccessLevel;导入lombok.RequiredArgsConstructor;导入lombok.AllArgsConstructor;导入lombok.NonNull;@RequiredArgsConstructor(staticName='of')@AllArgsConstructor(access=AccessLevel.PROTECTED)public class ConstructorExample{ private int x, y; @NonNull 私有T 描述; @NoArgsConstructor 公共静态类NoArgsExample { @NonNull 私有字符串字段; }}

不使用Lombok的示例如下:

公共类ConstructorExample{ 私有int x, y; @NonNull 私有T 描述; private ConstructorExample(T description) { if (description==null) throw new NullPointerException('description'); } this.description=描述; } public staticConstructorExampleof(T 描述) { return new ConstructorExample(描述); } @java.beans.ConstructorProperties({'x', 'y', 'description'}) protected ConstructorExample(int x, int y, T description) { if (description==null) throw new NullPointerException('description') ;这个.x=x;这个.y=y; this.description=描述; } public static class NoArgsExample { @NonNull 私有字符串字段;公共NoArgsExample() { } }}

3 Lombok工作原理分析

你会发现,使用Lombok时,只需要添加相应的注解即可,不需要为此编写任何代码。自动生成的代码是如何生成的?

核心点是注释的分析。 JDK5在引入注解的同时,也提供了两种解析方式。

运行时解析

对于运行时可以解析的注解,@Retention必须设置为RUNTIME,这样才能通过反射获取注解。 java.lang,reflect反射包提供了一个接口AnnotatedElement,它定义了几种获取注解信息的方法。 Class、Constructor、Field、Method、Package等都实现了这个接口。熟悉反射的朋友应该非常熟悉。熟悉这种解析方法。

编译时分析

编译时解析有两种机制,下面简单介绍一下:

1)注释处理工具

apt 是从JDK5 生成的。 JDK7已被标记为过期,不建议使用。在JDK8中已经被彻底删除了。从JDK6开始,可以使用Pluggable Annotation Processing API来替代它。 apt被替换的主要原因有两个:

api均在com.sun.mirror非标准包下

没有集成到javac中,需要额外运行

2)可插拔注释处理API

自JDK6 以来添加了https://jcp.org/en/jsr/detail?id=269。作为apt的替代方案,它解决了apt的两个问题。当javac执行时,它会调用实现API的程序,这样我们就可以对编译器进行一些增强。此时javac的执行流程如下:

Lombok本质上是一个实现“https://www.jcp.org/en/jsr/detail?id=269”的程序。在使用javac的过程中,其作用的具体过程如下:

javac分析源代码并生成抽象语法树(AST)

运行过程中调用实现“JSR 269 API”的Lombok程序

此时Lombok对第一步得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改语法树(AST),添加由getter 和setter 方法。

javac 使用修改后的抽象语法树(AST)生成字节码文件,即向类添加新节点(代码块)

看完Lombok源码,对应注解的实现在HandleXXX中。例如,@Getter注解的实现是HandleGetter.handle()。还有一些其他的类库也是通过这种方式实现的,比如https://github.com/google/auto、http://square.github.io/dagger/等。

4.Lombok的优缺点

优势:

可以以注解的形式自动生成构造函数、getters/setters、equals、hashcode、toString等方法,一定程度上提高了开发效率。

使代码简洁,无需过多关注相应的方法。

修改属性时,还简化了为这些属性生成的getter/setter 方法的维护。

缺点:

不支持重载多个参数构造函数

虽然省去了手动创建getter/setter方法的麻烦,但是却大大降低了源码的可读性和完整性,降低了阅读源码的舒适度。

5. 总结

虽然Lombok有很多优点,但是Lombok更类似于一个IDE插件,项目也需要依赖相应的jar包。 Lombok之所以依赖jar包,是因为编译时会用到它的注解。为什么说它类似于插件呢?因为使用时eclipse或者IntelliJ IDEA需要安装相应的插件。编译器编译时,通过操作AST(抽象语法树)来改变字节码生成。方向的改变意味着它正在改变Java语法。它不是像spring的依赖注入或mybatis的ORM那样的运行时特性,而是编译时特性。这里我个人感觉最不舒服的就是对插件的依赖!因为Lombok只是省去了一些手动生成代码的麻烦,但是IDE有快捷键可以帮助生成getter/setter等方法,也很方便。

知乎上一位大佬发表了对Lombok的一些看法:

这是一个低级插件,不推荐使用。随着JAVA发展到今天,各种插件也层出不穷。如何辨别各种插件的优缺点?它可以从架构的角度优化你的设计,提高应用程序性能,并实现高度的封装性和可扩展性……像lombok这样的插件不再只是插件,它们改变了你编写源代码的方式。其实,如果代码少了,你能写出来又怎么样?如果JAVA家族充满了这样的东西,那就只是一堆披着金属色的狗屎,迟早会被其他语言取代。

话虽粗,理论却不粗。试想一下,一个项目有很多像Lombok这样的插件。个人认为会大大降低阅读源码的舒适度。

虽然极不建议在属性的getter/setter中编写一些业务代码,但在多年的实际项目实践中,有时通过在getter/setter中添加一点业务代码,可以极大地提高某些业务场景的代码效率。简化。所谓的权衡,可能意味着此时放弃某些标准,获得极大的便利。

我现在坚信任何编程语言或插件都只是一个工具。工具再强大,也要看使用它的人,就像小米和步枪依然能战胜飞机和大炮一样。结合具体业务场景和实际项目情况,没有必要一味追求高端技术,最适合的才是王道。

Lombok有其独特的优点和无法避免的缺点。最好的办法就是熟悉其优缺点,并在实战中灵活运用。

参考:

https://projectlombok.org/features/

https://github.com/rzwitserloot/lombok?spm=a2c4e.11153940.blogcont59972.5.2aeb6d32hayLHv

https://www.zhihu.com/question/42348457

用户评论

一笑傾城゛

终于找到了关于 Lombok 的详细介绍!我之前想尝试用它简化代码,但一直没找到合适教程。你的博客讲得非常清晰,已经迫不及待想实践一下了。

    有17位网友表示赞同!

执念,爱

Lombok 确实可以提高开发效率,但我感觉它可能会导致代码的可读性降低。尤其是对于不熟悉 Lombok 的团队来说,阅读代码会比较费力。

    有8位网友表示赞同!

伤离别

这篇博客写的很不错,介绍了 Lombok 的基本概念和常用的注解。我之前用过一些 Lombok 的功能,比如 @Data 和 @Setter,但还有很多新的特性还没有了解清楚。我会仔细阅读你的文章,希望能深入理解它。

    有17位网友表示赞同!

孤廖

我一直觉得 IDE 自动生成 Getters/Setters 太繁琐了,Lombok 能帮我节省不少时间和精力!不过文档上说 Lombok 会增加运行时的开销,这让我有点担忧,不知道实际影响有多大?

    有6位网友表示赞同!

龙卷风卷走爱情

我是 Java 新手,之前一直在探索项目开发过程中如何提高效率。看到这个标题就觉得很有兴趣,希望博客能详细讲解一下 Lombok 的使用方法和优缺点,以便我更好地理解它的应用场景。

    有15位网友表示赞同!

迷路的男人

Lombok 的一个比较好的地方就是它能够让代码更加简洁,尤其是对于那些重复性的代码块来说。不过要记住,过度的使用注解可能会使代码难以理解,所以需要适度使用,才能发挥其最大的作用。

    有11位网友表示赞同!

■孤独像过不去的桥≈

Lombok 确实可以提高开发效率,但是我比较担心它会降低代码的可维护性和可读性。如果一个项目有多个开发者协同工作,缺乏对 Lombok 的统一理解可能会导致沟通困难,增加代码调试的难度。

    有9位网友表示赞同!

苍白的笑〃

非常感谢博主分享这篇深入浅出的文章!我的 Java 生涯已经走了一些年头了,Lombok 虽然不是第一次接触,但博主的讲解仍然让我受益匪浅,尤其是在使用 Lombok 构建 API 和数据结构方面给出了很多实用建议,我打算尽快将这些知识应用到我的项目中去。

    有9位网友表示赞同!

◆乱世梦红颜

总觉得 Java 代码写起来有时候会比较繁琐,很高兴看到有人介绍了 Lombok 这类工具。期待下期博主能分享一下Lombok 与某些主流框架的兼容性以及一些实际案例分析,以便更全面地了解它的应用场景。

    有11位网友表示赞同!

花开丶若相惜

学习完了这篇博客后对 Lombok 有了一个初步的理解。主要想问一下使用 Lombok 之后测试代码的方式有什么改变吗?

    有17位网友表示赞同!

妄灸

lombok 一直在想用这个强大的框架简化代码,但还没找到合适的时机去应用它!这篇文章讲解得很到位,尤其是使用方法部分非常实用,我已经着手在我的项目中尝试使用了Lombok。

    有8位网友表示赞同!

刺心爱人i

我之前也在研究 Lombok, 看了你的博客对它的总结有更深入的了解了,特别是关于使用场景的选择,需要更加慎重, 才能发挥Lombok的最大效用。我会继续学习更多相关的资料!

    有16位网友表示赞同!

陌上蔷薇

这篇文章写的太好了!终于可以对lombok有一个清楚的认识了,之前一直在做 Java 开发却不知道这个框架居然能带来如此巨大的方便!我马上就把它应用到我的项目中去试试!

    有12位网友表示赞同!

醉枫染墨

Lombok 确实厉害,可以让代码简洁很多,不过对于初学 Java 的同学来说,可能会比较难以理解 Lombok 的语法和注解的使用。建议博主可以加入一些图文并茂的示例和案例分析,帮助读者更直观地理解它的使用方法。

    有12位网友表示赞同!

那伤。眞美

我主要关注的是 Kotlin 开发,这个 Lombok 介绍是否能适用于 Kotlin?

    有19位网友表示赞同!

熏染

我一直在寻找高效提高 Java 开发效率的方式,Lombok 作为一种受欢迎的框架,我一直想尝试使用它。这篇博文介绍得非常清晰,我已经开始学习使用它的注解,相信在以后开发中可以大大减少重复代码的书写工作。

    有17位网友表示赞同!

发型不乱一切好办

这篇博客讲解了 Lombok 的基本概念和用法,让我对这个工具有了初步的了解。不过我想要知道,Lombok 是否支持所有 Java 类型以及不同版本的兼容性如何?

    有20位网友表示赞同!

热点资讯