千家信息网

Lombok的作用和使用方法

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容介绍了"Lombok的作用和使用方法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Lombo
千家信息网最后更新 2026年11月02日Lombok的作用和使用方法

本篇内容介绍了"Lombok的作用和使用方法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

Lombok使用方法

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.projectlombok    lombok    1.16.20    provided

@Data

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

 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 {    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 {    private final String name;    private final T value;        private Exercise(String name, T value) {      this.name = name;      this.value = value;    }        public static  Exercise of(String name, T value) {      return new Exercise(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;    }  }}

@Getter/@Setter

如果觉得@Data太过残暴(因为@Data集合了@ToString、@EqualsAndHashCode、@Getter/@Setter、@RequiredArgsConstructor的所有特性)不够精细,可以使用@Getter/@Setter注解,此注解在属性上,可以为相应的属性自动生成Getter/Setter方法,示例如下:

 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;  }}

@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()方法,很大的简化了代码。

示例如下:

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();      }    }  }}

@EqualsAndHashCode

默认情况下,会使用所有非静态(non-static)和非瞬态(non-transient)属性来生成equals和hasCode,也能通过exclude注解来排除一些属性。

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;    }  }}

@ToString

类使用@ToString注解,Lombok会生成一个toString()方法,默认情况下,会输出类名、所有属性(会按照属性定义顺序),用逗号来分割。

通过将includeFieldNames参数设为true,就能明确的输出toString()属性。这一点是不是有点绕口,通过代码来看会更清晰些。

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) + ")";  }}

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

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

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

不使用Lombok的示例如下:

 public class ConstructorExample {  private int x, y;  @NonNull private T description;    private ConstructorExample(T description) {    if (description == null) throw new NullPointerException("description");    this.description = description;  }    public static  ConstructorExample of(T description) {    return new ConstructorExample(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() {    }  }}

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源码,对应注解的实现都在HandleXXX中,比如@Getter注解的实现时HandleGetter.handle()。还有一些其它类库使用这种方式实现,比如Google Auto、Dagger等等。

Lombok的优缺点

优点:

  1. 能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率

  2. 让代码变得简洁,不用过多的去关注相应的方法

  3. 属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

缺点:

  1. 不支持多种参数构造器的重载

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

总结

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

"Lombok的作用和使用方法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 注解 属性 生成 代码 构造器 编译 语法 参数 就是 过程 运行 插件 方式 示例 自动生成 开发 作用 使用方法 字节 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 新华互联网科技 深圳九邦互联网科技有限公司 互联网科技工作委员会 新华互联网科技学校 互联网科技社 科技互联网创业计划书 新华互联网科技校企合作 恒生科技互联网指数分析 湖北码尼互联网科技有限公司电话 宜昌元轩互联网科技有限公司 中国互联网公司排名锤子科技 南通创西澳互联网科技有限公司 广州千川互联网科技有限公司 互联网科技股为什么大涨 中国新注册互联网科技 求路客互联网科技电话 广州三三互联网科技有限公司 数字科技和互联网金融哪个好 每日互联网科技新闻 武汉亿视互联网科技有限公司 互联网与科技 互联网与新科技 齐家互联网科技有限公司 宁波青枫互联网科技有限公司 科技与互联网哪个更好 重庆威客帮互联网科技 互联网还是高科技吗 呼和浩特新华互联网科技学院 佛山市翊博互联网络科技有限公司 网互联网络科技
0