lombok的介绍及使用

2024-06-14 20:58
文章标签 使用 介绍 lombok

本文主要是介绍lombok的介绍及使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、lombok介绍:

二、官网:http://projectlombok.org/ ;

三、安装:

四、引入依赖:

五、有哪些注解:

六、注解详细说明:@Data

七、@Accessors(chain = true)

八、Lombok工作原理分析

九、Lombok的优缺点


一、lombok介绍:

     就是通过@Data注解的方式省去了我们平时开发定义JavaBean之后,生成其属性的构造器、getter、setter、equals、hashcode、toString方法;但是,在编译时会自动生成这些方法,在.class文件中。

二、官网:http://projectlombok.org/ ;

文档地址:http://projectlombok.org/features/index.

三、安装:

     打开 IDEA 的 Settings 面板,并选择 Plugins 选项,然后点击 “Browse repositories”

在输入框输入”lombok”,得到搜索结果,点击安装,然后安装提示重启 IDEA,安装成功;

四、引入依赖:

maven项目:在自己的项目里添加 lombok 的编译支持,在 pom 文件里面添加 dependency

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.18</version><scope>provided</scope>
</dependency>

非maven项目:首先下载lombok.jar包:https://projectlombok.org/download.html

   具体引用方式不做详细讲解,跟其他jar引入方式一样

五、有哪些注解:

  • @Data
  • @Setter
  • @Getter
  • @Log4j
  • @Slf4j
  • @AllArgsConstructor
  • @NoArgsConstructor
  • @EqualsAndHashCode
  • @NonNull
  • @Cleanup
  • @ToString
  • @RequiredArgsConstructor
  • @Value
  • @SneakyThrows
  • @Synchronized
  • @Accessors(chain = true)
  • 还有一些注解 @builder @Singular @Delegate @Accessors @Wither @val @UtilityClass

    等就不在做详细说明 有需要的可以自行百度哈

六、注解详细说明:
@Data

注解在 类 上;提供类所有属性的 get 和 set 方法,此外还提供了equals、canEqual、hashCode、toString 方法。

官方实例:

import lombok.AccessLevel;
import lombok.Setter;
import lombok.Data;
import lombok.ToString;@Data public class DataExample {private final String name;@Setter(AccessLevel.PACKAGE) private int age;private double score;private String[] tags;@ToString(includeFieldNames=true)@Data(staticConstructor="of")public static class Exercise<T> {private final String name;private final T value;}
}

使用Lombok,则实现如下:

import java.util.Arrays;public class DataExample {private final String name;private int age;private double score;private String[] tags;public DataExample(String name) {this.name = name;}public String getName() {return this.name;}void setAge(int age) {this.age = age;}public int getAge() {return this.age;}public void setScore(double score) {this.score = score;}public double getScore() {return this.score;}public String[] getTags() {return this.tags;}public void setTags(String[] tags) {this.tags = tags;}@Override public String toString() {return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";}protected boolean canEqual(Object other) {return other instanceof DataExample;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof DataExample)) return false;DataExample other = (DataExample) o;if (!other.canEqual((Object)this)) return false;if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;if (this.getAge() != other.getAge()) return false;if (Double.compare(this.getScore(), other.getScore()) != 0) return false;if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;final long temp1 = Double.doubleToLongBits(this.getScore());result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());result = (result*PRIME) + this.getAge();result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));result = (result*PRIME) + Arrays.deepHashCode(this.getTags());return result;}public static class Exercise<T> {private final String name;private final T value;private Exercise(String name, T value) {this.name = name;this.value = value;}public static <T> Exercise<T> of(String name, T value) {return new Exercise<T>(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 Exercise;}@Override public boolean equals(Object o) {if (o == this) return true;if (!(o instanceof Exercise)) return false;Exercise<?> other = (Exercise<?>) o;if (!other.canEqual((Object)this)) return false;if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;return true;}@Override public int hashCode() {final int PRIME = 59;int result = 1;result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());return result;}}
}

@Setter @Getter

可以作用在类上和属性上,提供默认构造方法。

放在类上,会对所有的非静态(non-static)属性生成Getter/Setter方法,可以定义等级

Lombok 同样为我们提供了一些可以设置当前类似访问权限或者禁止生成某个方法函数,它就是 AccessLevel,其中它对应以下俩种场景:

  • PUBLIC,PROTECTED,PACKAGE,和PRIVATE:设置访问级别;

  • NONE:禁止生成某个对应的 get / set

放在属性上,会对该属性生成Getter/Setter方法。

使用lombok:

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;public class GetterSetterExample {@Getter @Setter private int age = 10;@Setter(AccessLevel.PROTECTED) private String name;@Override public String toString() {return String.format("%s (age: %d)", name, age);}
}

不适用lombok:

public class GetterSetterExample {private int age = 10;private String name;@Override public String toString() {return String.format("%s (age: %d)", name, age);}public int getAge() {return age;}public void setAge(int age) {this.age = age;}protected void setName(String name) {this.name = name;}
}

@Log4j

注解在 类 上;为类提供一个 属性名为 log 的 log4j 日志对象,提供默认构造方法。

使用lombok:

不使用lombok:

@Slf4j:

注解在 类 上;为类提供一个 属性名为 log 的 slf4j日志对象,提供默认构造方法。

@AllArgsConstructor

注解在 类 上;为类提供一个全参的构造方法,加了这个注解后,类中不提供默认构造方法了。

@NoArgsConstructor

注解在 类 上;为类提供一个无参的构造方法。

@RequiredArgsConstructor

这个注解用在 类 上,使用类中所有带有 @NonNull 注解的或者带有 final 修饰的成员变量生成对应的构造方法。

使用lombok:

import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample<T> {private int x, y;@NonNull private T description;@NoArgsConstructorpublic static class NoArgsExample {@NonNull private String field;}
}


不使用lombok:

public class ConstructorExample<T> {private int x, y;@NonNull private T description;private ConstructorExample(T description) {if (description == null) throw new NullPointerException("description");this.description = description;}public static <T> ConstructorExample<T> of(T description) {return new ConstructorExample<T>(description);}@java.beans.ConstructorProperties({"x", "y", "description"})protected ConstructorExample(int x, int y, T description) {if (description == null) throw new NullPointerException("description");this.x = x;this.y = y;this.description = description;}public static class NoArgsExample {@NonNull private String field;public NoArgsExample() {}}
}

@EqualsAndHashCode

注解在 类 上, 可以生成 equals、canEqual、hashCode 方法。

使用lombok:

import lombok.EqualsAndHashCode;@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {private transient int transientVar = 10;private String name;private double score;private Shape shape = new Square(5, 10);private String[] tags;private int id;public String getName() {return 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 = height;}}
}

 

@NonNull

注解在 属性 上,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常,也会有一个默认的无参构造方法。

使用lombok:

import lombok.NonNull;public class NonNullExample extends Something {private String name;public NonNullExample(@NonNull Person person) {super("Hello");this.name = person.getName();}
}

不使用lombok:

import lombok.NonNull;public class NonNullExample extends Something {private String name;public NonNullExample(@NonNull Person person) {super("Hello");if (person == null) {throw new NullPointerException("person");}this.name = person.getName();}
}

@Cleanup

这个注解用在 变量 前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的 close() 方法,如果该资源有其它关闭方法,可使用 @Cleanup(“methodName”) 来指定要调用的方法,也会生成默认的构造方法

使用lombok:

import lombok.Cleanup;
import 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 = new byte[10000];while (true) {int r = in.read(b);if (r == -1) break;out.write(b, 0, r);}}
}

不使用lombok:

import java.io.*;public class CleanupExample {public static void main(String[] args) throws IOException {InputStream in = new FileInputStream(args[0]);try {OutputStream out = new FileOutputStream(args[1]);try {byte[] b = new byte[10000];while (true) {int r = in.read(b);if (r == -1) break;out.write(b, 0, r);}} finally {if (out != null) {out.close();}}} finally {if (in != null) {in.close();}}}
}

@ToString

使用exclude属性来控制某几个字段不出现在toString方法的结果中;
使用includeFieldNames,of 属性来控制是否在toString方法的结果中出现成员变量的名称;
使用doNotUseGetters属性来控制在toString方法中是否使用getter方法来访问变量的值;
使用callSuper属性来控制是否要调用父类的toString方法,即在子类的toString方法输出时,是否同时将父类的成员一同输

这个注解用在 类 上,默认情况下,会输出类名、所有属性,属性会按照顺序输出,以逗号分割,还会生成默认的构造方法。

使用lombok:

import lombok.ToString;@ToString(exclude="id")
public class ToStringExample {private static final int STATIC_VAR = 10;private String name;private Shape shape = new Square(5, 10);private String[] tags;private int id;public String 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 = height;}}
}

不使用lombok:

import java.util.Arrays;public class ToStringExample {private static final int STATIC_VAR = 10;private String name;private Shape shape = new Square(5, 10);private String[] tags;private int id;public String 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 = 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) + ")";}
}

@ToString(exclude="column")

意义:排除column列所对应的元素,即在生成toString方法时不包含column参数;

@ToString(exclude={"column1","column2"})

意义:排除多个column列所对应的元素,其中间用英文状态下的逗号进行分割,即在生成toString方法时不包含多个column参数;

@ToString(of="column")

意义:只生成包含column列所对应的元素的参数的toString方法,即在生成toString方法时只包含column参数;;

@ToString(of={"column1","column2"})

意义:只生成包含多个column列所对应的元素的参数的toString方法,其中间用英文状态下的逗号进行分割,即在生成toString方法时只包含多个column参数;

@Value 可参考@Data

这个注解用在 类 上,会生成含所有参数的构造方法,get 方法,此外还提供了equals、hashCode、toString 方法。

@SneakyThrows

这个注解用在 方法 上,可以将方法中的代码用 try-catch 语句包裹起来,捕获异常并在 catch 中用 Lombok.sneakyThrow(e) 把异常抛出,可以使用 @SneakyThrows(Exception.class) 的形式指定抛出哪种异常,也会生成默认的构造方法。

使用lombok:

import lombok.SneakyThrows;
import java.io.FileInputStream;
import java.io.IOException;public class SneakyThrowsTest {@SneakyThrows(IOException.class)public static void main(String[] args) {new FileInputStream(args[0]);}
}


不使用lombok:

import java.io.FileInputStream;
import java.io.IOException;public class SneakyThrowsTest {public SneakyThrowsTest() {}public static void main(String[] args) {try {new FileInputStream(args[0]);} catch (IOException var2) {throw var2;}}
}

@Synchronized

这个注解用在 类方法 或者 实例方法 上,效果和 synchronized 关键字相同,区别在于锁对象不同,对于类方法和实例方法,synchronized 关键字的锁对象分别是类的 class 对象和 this 对象,而 @Synchronized 的锁对象分别是 私有静态 final 对象 lock 和 私有 final 对象 lock,当然,也可以自己指定锁对象,此外也提供默认的构造方法。

使用lombok:

import lombok.Synchronized;public class SynchronizedTest {private final Object readLock = new Object();@Synchronizedpublic static void sayHello(){System.out.println("hello world");}@Synchronizedpublic int sayName(){return  30;}@Synchronized("readLock")public void read(){System.out.println("I am reading");}
}


不使用lombok:

public class SynchronizedTest {private static final Object $LOCK = new Object[0];private final Object $lock = new Object[0];private final Object readLock = new Object();public SynchronizedTest() {}public static void sayHello() {Object var0 = $LOCK;synchronized($LOCK) {System.out.println("hello world");}}public int sayName() {Object var1 = this.$lock;synchronized(this.$lock) {return 30;}}public void read() {Object var1 = this.readLock;synchronized(this.readLock) {System.out.println("I am reading");}}

七、@Accessors(chain = true)

该注解配合 @Getter  @Setter 可进行链式编程,美化代码

@Accessors(chain = true)
@Getter
@Setter
public class StudentBean {private String name;private int age;public static void main(String[] args) {StudentBean studentBean = new StudentBean().setName("test").setAge(1);System.out.println("name:" +studentBean.getName());}
}

八、Lombok工作原理分析

会发现在Lombok使用的过程中,只需要添加相应的注解,无需再为此写任何代码。自动生成的代码到底是如何产生的呢?

核心之处就是对于注解的解析上。JDK5引入了注解的同时,也提供了两种解析方式。

  • 运行时解析

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

  • 编译时解析

编译时解析有两种机制,分别简单描述下:

1)Annotation Processing Tool

apt自JDK5产生,JDK7已标记为过期,不推荐使用,JDK8中已彻底删除,自JDK6开始,可以使用Pluggable Annotation Processing API来替换它,apt被替换主要有2点原因:

  • api都在com.sun.mirror非标准包下
  • 没有集成到javac中,需要额外运行

2)Pluggable Annotation Processing API

JSR 269自JDK6加入,作为apt的替代方案,它解决了apt的两个问题,javac在执行的时候会调用实现了该API的程序,这样我们就可以对编译器做一些增强,这时javac执行的过程如下: 
这里写图片描述

Lombok本质上就是一个实现了“JSR 269 API”的程序。在使用javac的过程中,它产生作用的具体流程如下:

  1. javac对源代码进行分析,生成了一棵抽象语法树(AST)
  2. 运行过程中调用实现了“JSR 269 API”的Lombok程序
  3. 此时Lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
  4. javac使用修改后的抽象语法树(AST)生成字节码文件,即给class增加新的节点(代码块)

九、Lombok的优缺点

优点:

  1. 能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率
  2. 让代码变得简洁,不用过多的去关注相应的方法
  3. 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

缺点:

  1. 不支持多种参数构造器的重载
  2. 虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性,降低了阅读源代码的舒适度
  3. 通过idea工具生成java doc 文档时,无法生成实体类的get set方法

这篇关于lombok的介绍及使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1061487

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

oracle DBMS_SQL.PARSE的使用方法和示例

《oracleDBMS_SQL.PARSE的使用方法和示例》DBMS_SQL是Oracle数据库中的一个强大包,用于动态构建和执行SQL语句,DBMS_SQL.PARSE过程解析SQL语句或PL/S... 目录语法示例注意事项DBMS_SQL 是 oracle 数据库中的一个强大包,它允许动态地构建和执行

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详