Lombok常用注解介绍

1.什么是Lombok?

Lombok是一款Java开发插件,使得Java开发者可以通过其定义的一些注解来消除业务工程中冗长和繁琐的代码,尤其对于简单的Java模型对象(POJO)。 在开发环境中使用Lombok插件后,Java开发人员可以节省出重复构建,诸如hashCode和equals这样的方法以及各种业务对象模型的accessor和ToString等方法的大量时间。对于这些方法,它能够在编译源代码期间自动帮我们生成这些方法,并没有如反射那样降低程序的性能。

2.常用注解

@NoArgsConstructor/@AllArgsConstructor

@NoArgsConstructor/@AllArgsConstructor就是为该类产生无参的构造方法和包含所有参数的构造方法

/** * @ClassName User * @Description TODO * @Author liuhaihua * @Date 2024/9/17 17:20 * @Version 1.0 */@AllArgsConstructorpublic class User {   private String name;   private int age;}

  生成的代码如下

package com.et.lombok.model;

public class User {
private String name;
private int age;

public User(final String name, final int age) {
this.name = name;
this.age = age;
}
}

@RequiredArgsConstructor

@RequiredArgsConstructor注解则会将类中所有带有@NonNull注解 / org.jetbrains.annotations.NotNull注解的或者带有final修饰的成员变量生成对应的构造方法

package com.et.lombok.model;
import lombok.NonNull;import lombok.RequiredArgsConstructor;
@RequiredArgsConstructorpublic class Demo { @NonNull private String name; @NonNull private int age;}

生成的代码如下

package com.et.lombok.model;
import lombok.NonNull;
public class Demo { @NonNull private String name; @NonNull private int age;
public Demo(@NonNull final String name, @NonNull final int age) { if (name == null) { throw new NullPointerException("name is marked non-null but is null"); } else { this.name = name; this.age = age; } }}

@Getter/@Setter

这一对注解从名字上就很好理解,用在成员变量上面或者类上面,相当于为成员变量生成对应的get和set方法,同时还可以为生成的方法指定访问修饰符,当然,默认为public

package com.et.lombok.model;
import lombok.Getter;import lombok.NonNull;import lombok.RequiredArgsConstructor;import lombok.Setter;
@Getter@Setterpublic class Demo1 { private String name; private int age;}

生成的代码

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
public class Demo1 { private String name; private int age;
public Demo1() { }
public String getName() { return this.name; }
public int getAge() { return this.age; }
public void setName(final String name) { this.name = name; }
public void setAge(final int age) { this.age = age; }}
这两个注解直接用在类上,可以为此类里的所有非静态成员变量生成对应的get和set方法。如果是final变量,那就只会有get方法

@ToString/@EqualsAndHashCode

这两个注解也比较好理解,就是生成toString,equals和hashcode方法,同时后者还会生成一个canEqual方法,用于判断某个对象是否是当前类的实例。生成方法时只会使用类中的非静态成员变量。

package com.et.lombok.model;
import lombok.EqualsAndHashCode;import lombok.ToString;

@ToString(exclude="id")@EqualsAndHashCodepublic class ToStringExample { private static final int STATIC_VAR = 10; private String name; private String[] tags; private int id;
}

生成的类如下

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
import java.util.Arrays;
public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private String[] tags; private int id;
public ToStringExample() { }
public String toString() { return "ToStringExample(name=" + this.name + ", tags=" + Arrays.deepToString(this.tags) + ")"; }
public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof ToStringExample)) { return false; } else { ToStringExample other = (ToStringExample)o; if (!other.canEqual(this)) { return false; } else { label31: { Object this$name = this.name; Object other$name = other.name; if (this$name == null) { if (other$name == null) { break label31; } } else if (this$name.equals(other$name)) { break label31; }
return false; }
if (!Arrays.deepEquals(this.tags, other.tags)) { return false; } else { return this.id == other.id; } } } }
protected boolean canEqual(final Object other) { return other instanceof ToStringExample; }
public int hashCode() { int PRIME = true; int result = 1; Object $name = this.name; int result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + Arrays.deepHashCode(this.tags); result = result * 59 + this.id; return result; }}

@Data

@Data 相当于注解集合。效果等同于 @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor 效果同和这5个注解的效果

需要注意的是,这里不包括@NoArgsConstructor和@AllArgsConstructor 所以, 一般使用@Data时,要配合这两个注解一起使用
package com.et.lombok.model;
import lombok.Data;import lombok.Getter;import lombok.Setter;
@Datapublic class Demo3 { private String name; private int age;}

生成的代码

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
public class Demo3 { private String name; private int age;
public Demo3() { }
public String getName() { return this.name; }
public int getAge() { return this.age; }
public void setName(final String name) { this.name = name; }
public void setAge(final int age) { this.age = age; }
public boolean equals(final Object o) { if (o == this) { return true; } else if (!(o instanceof Demo3)) { return false; } else { Demo3 other = (Demo3)o; if (!other.canEqual(this)) { return false; } else { Object this$name = this.getName(); Object other$name = other.getName(); if (this$name == null) { if (other$name == null) { return this.getAge() == other.getAge(); } } else if (this$name.equals(other$name)) { return this.getAge() == other.getAge(); }
return false; } } }
protected boolean canEqual(final Object other) { return other instanceof Demo3; }
public int hashCode() { int PRIME = true; int result = 1; Object $name = this.getName(); int result = result * 59 + ($name == null ? 43 : $name.hashCode()); result = result * 59 + this.getAge(); return result; }
public String toString() { return "Demo3(name=" + this.getName() + ", age=" + this.getAge() + ")"; }}

@Builder

@Builder提供了一种比较推崇的构建值对象的方式; 非常推荐的一种构建值对象的方式。 缺点就是父类的属性不能产于builder

标注@Builder的类, 会在类内部生成一个内部类,用于生成值对象
package com.et.lombok.model;
import lombok.Builder;
@Builderpublic class Demo4 { private String name; private int age;}

生成的代码

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
public class Demo4 { private String name; private int age;
Demo4(final String name, final int age) { this.name = name; this.age = age; }
public static Demo4.Demo4Builder builder() { return new Demo4.Demo4Builder(); }
public static class Demo4Builder { private String name; private int age;
Demo4Builder() { }
public Demo4.Demo4Builder name(final String name) { this.name = name; return this; }
public Demo4.Demo4Builder age(final int age) { this.age = age; return this; }
public Demo4 build() { return new Demo4(this.name, this.age); }
public String toString() { return "Demo4.Demo4Builder(name=" + this.name + ", age=" + this.age + ")"; } }}

用法

package com.et.lombok.model;
import com.et.lombok.model.Demo4;
public class Main {
public static void main(String[] args) { Demo4 demo = Demo4.builder().name("zss").age(20).build(); System.out.println(demo); }}

@Accessors

@Accessors 一个为getter和setter方法设计的更流畅的注解 这个注解要搭配@Getter与@Setter使用,用来修改默认的setter与getter方法的形式。 @Accessors属性详解

  • fluent 属性 : 链式的形式 这个特别好用,方法连缀越来越方便了

  • chain 属性 : 流式的形式(若无显示指定chain的值,也会把chain设置为true)

  • prefix 属性 : 生成指定前缀的属性的getter与setter方法,并且生成的getter与setter方法时会去除前缀

package com.et.lombok.model;
import lombok.Builder;import lombok.Getter;import lombok.Setter;import lombok.ToString;import lombok.experimental.Accessors;
@Getter@Setter@ToString@Accessors(fluent = true)public class Demo5 { private String name; private int age;}

代码如下

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
public class Demo5 { private String name; private int age;
public Demo5() { }
public String name() { return this.name; }
public int age() { return this.age; }
public Demo5 name(final String name) { this.name = name; return this; }
public Demo5 age(final int age) { this.age = age; return this; }
public String toString() { return "Demo5(name=" + this.name() + ", age=" + this.age() + ")"; }}

@SneakyThrows

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

package com.et.lombok.model;
import lombok.SneakyThrows;
import java.io.UnsupportedEncodingException;
public class Main1 {
@SneakyThrows(UnsupportedEncodingException.class) public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF8"); }
}

生成的代码

//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
import java.io.UnsupportedEncodingException;
public class Main1 { public Main1() { }
public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF8"); } catch (UnsupportedEncodingException var3) { throw var3; } }}

@Value

@Value注解和@Data类似,区别在于它会把所有成员变量默认定义为private final修饰,并且不会生成set方法。

@Cleanup

这个注解用在局部变量上,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法。 如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法,就用输入输出流来举个例子吧:

package com.et.lombok.model;
import lombok.Cleanup;import lombok.SneakyThrows;
import java.io.*;
public class Main2 { @SneakyThrows(Exception.class) public static void main(String[] args) { @Cleanup InputStream in = new FileInputStream(args[0]); @Cleanup OutputStream out = new FileOutputStream(args[1]); byte[] b = new byte[1024]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } }
}

生成的代码



//// Source code recreated from a .class file by IntelliJ IDEA// (powered by FernFlower decompiler)//
package com.et.lombok.model;
import java.io.FileInputStream;import java.io.FileOutputStream;import java.util.Collections;
public class Main2 { public Main2() { }
public static void main(String[] args) { try { FileInputStream in = new FileInputStream(args[0]);
try { FileOutputStream out = new FileOutputStream(args[1]);
try { byte[] b = new byte[1024];
while(true) { int r = in.read(b); if (r == -1) { return; }
out.write(b, 0, r); } } finally { if (Collections.singletonList(out).get(0) != null) { out.close(); }
} } finally { if (Collections.singletonList(in).get(0) != null) { in.close(); }
} } catch (Exception var15) { throw var15; } }}

@NotNull

这个注解可以用在成员方法或者构造方法的参数上,会自动产生一个关于此参数的非空检查,如果参数为空,则抛出一个空指针异常。

@Synchronized

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

注意: 属性value指定锁对象,当锁对象不存在时,则编译不通过,默认为 “”

@Slf4j注解

Slf4j日志门面(Simple Logging Facade For Java) , Slf4j主要是为了给Java日志访问提供一套标准、规范的API框架,其主要意义在于提供接口,具体的实现可以交由其他日志框架,例如log4j和logback等    

相关推荐

  • 这个python库简直是office办公利器~
  • 实时数仓行业方案!
  • o1方法性能无上限!姚班马腾宇等数学证明:推理token够多,就能解决任意问题
  • 倒计时三年:国产数据库100%替代走到哪了?
  • 作者硬核,内容透彻接地气的多模态大模型通识读本 | 留言赠书
  • 成都周报丨清华成立百亿母基金,成渝国资再次联手出资
  • 422页新书《构建实用的全栈机器学习指南》pdf下载
  • 大厂也是草台班子!
  • 超越AlphaFold3,OpenAI投资的AI生物初创发布Chai-1,分子结构预测新SOTA
  • 华为诺亚联合中科大发布工具调用模型ToolACE,效果持平GPT-4获开源第一
  • 「LLM」这个名字不好,Karpathy认为不准确、马斯克怒批太愚蠢
  • DeepMind又损大将,AI总监Nando de Freitas离职,曾领导开发Gato、Genie
  • 北大对齐团队独家解读:OpenAI o1开启「后训练」时代强化学习新范式
  • 极简机器人开发,助力高效部署生成式AI模型
  • 360视角:大模型幻觉问题及其解决方案的深度探索与实践
  • 阿里云盘惊现逆天 Bug,创建相册后可随意观看他人照片!
  • 历时两年半,我们 “搬家” 了!
  • KAN干翻MLP,开创神经网络新范式!一个数十年前数学定理,竟被MIT华人学者复活了
  • Nature:探秘世界最快超算的一天
  • 拯救OpenAI 1500亿估值,就靠o1了?全新Scaling Law终结奥特曼「非营利游戏」