Lombok 注解及实例大全

2023-10-27

Project Lombok是一个java库,它可以自动插入到编辑器和构建工具中,为Java增添趣味。 永远不要再编写另一个getter或equals方法,只要有一个注释,你的类就有一个功能齐全的构建器,自动化你的日志变量,等等。

val

用在局部变量前面,相当于将变量声明为 final

val map = new HashMap<String, String>();
// 相当于
final Map<String, String> map = new HashMap<>();

但是这个功能不能再 IDEA 中正确运行

@NonNull

给 属性、方法参数 增加这个注解会自动在方法内对该参数进行是否为空的校验。

形参前加上@NonNull,当传入参数为null时,会抛出 NPE(NullPointerException)

不加@NonNull,会打印结果null,不会抛异常

修饰属性:

public class UserLombok {
    private Long id;

    private String name;

    @NonNull
    private String school;
}

修饰方法参数:

public void testNonNull(@NonNull String name) {
    System.out.println(name);
}

// 相当于
public void testNonNull(String name) {
    if (name != null) {
        System.out.println(name);
    } else {
        throw new NullPointerException("null");
    }
}

@Cleanup

自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成 try-finally 这样的代码来关闭流

public static void main(String[] args) {
    try {
        @Cleanup InputStream inputStream = new FileInputStream(args[0]);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    
    // 相当于
    InputStream inputStream = null;
    try {
        inputStream = new FileInputStream(args[0]);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

@Getter/@Setter

标注在类上

标注在类上,表示针对该类中所有的非静态字段进行 get、set 方法自动生成。

标注在字段上

标注在字段上,用于自动生成 get、set 方法,boolean 类型字段 get 方法为 isXXX() 方法。

生成的 get、set 方法默认情况下都是 public 的,但也可以手动指定以下四种范围:

  • AccessLevel.PUBLIC
  • AccessLevel.MODULE
  • AccessLevel.PROTECTED
  • AccessLevel.PACKAGE
  • AccessLevel.PRIVATE
@Data
public class User {

    private String name;

    @Setter(AccessLevel.PRIVATE)  // 生成的Setter方法是private的
    private String address;

    @Setter @Getter(AccessLevel.PRIVATE)  // 生成的Setter和Getter方法是private的
    private String phone;
}

如果指定某个字段的 AccessLevel = AccessLevel.NONE,则可以使该生成动作失效,此时可以手动实现get、set方法,AccessLevel.NONE 可以应用于在某些方法中有一些自定义逻辑的情况下。

@Getter
@Setter
public class User {
    private String name;
    
    private Integer age;

    @Getter(value = AccessLevel.NONE)
    private boolean child;

    public boolean isChild() {
        if(age < 12) {
            return true;
        }
        return false;
    }
}

@ToString

用在类上可以自动覆写 toString 方法,当然还可以加其他参数

例如 @ToString(exclude=”id”) 排除 id 属性,@ToString(exclude={"id", "name"})排除多个属性

或者 @ToString(callSuper=true, includeFieldNames=true) 调用父类的 toString 方法,包含所有属性

@ToString(exclude = "id", callSuper = true, includeFieldNames = true)
publicclass LombokDemo {
    private int id;
    private String name;
    private int age;
    public static void main(String[] args) {
        // 输出 LombokDemo(super=LombokDemo@48524010, name=null, age=0)
        System.out.println(new LombokDemo());
    }
}

@EqualsAndHashCode

用在类上自动生成 equals(Object other)hashcode() 方法,包括所有非静态变量和非 transient 的变量

@EqualsAndHashCode(exclude = {"id", "name"}, callSuper = false)
public class User {
    private int id;
    private String name;
}

为什么要重写hashcode和equals方法

为什么只有一个整体的 @EqualsAndHashCode 注解,而不是分开的两个 @Equals@HashCode

  • 在 Java 中有规定,当两个对象 equals 时,他们的 hashcode 一定要相同,反之,当 hashcode 相同时,对象不一定 equals。所以 equals 和 hashcode 要一起实现,免得发生违反 Java 规定的情形发生

@Data

lombok 项目的产生就是为了省去我们手动创建getter和setter等基本方法的麻烦,它能够在我们编译源码的时候自动帮我们生成getter和setter等方法。即它最终能够达到的效果是:在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法

注意:@EqualsAndHashCode注解与@ToString注解默认情况下是忽略父类的成员变量的。

在类继承的情况时应注意@Data注解不会涉父类的成员的坑,需要加callSuper = true的参数。

@Data 是整合包,只要加了 @Data 这个注解,等于同时加了以下注解

  • @Getter/@Setter
  • @ToString
  • @EqualsAndHashCode
  • @RequiredArgsConstructor

@NoArgsConstructor

@AllArgsConstructor

@RequiredArgsConstructor

@NoArgsConstructor

用在类上,自动生成无参构造器

@AllArgsConstructor

用在类上,自动生成使用所有参数的构造器

@RequiredArgsConstructor

用在类上,生成一个包含 “特定参数” 的构造器,特定参数指的是所有被 final 修饰的变量

把所有 被@NonNull 或者 final 修饰的属性作为参数的构造函数

@RequiredArgsConstructor
public class UserLombok {
    private Long id;

    private String name;

    private String phoneNo;

    private final String address;

    @NonNull
    private String school;
}

则会生成一个包含address和school的构造函数

指定 staticName=“of” 参数

如果指定 staticName=“of” 参数,同时还会生成一个返回类对象的静态工厂方法,比使用构造函数方便很多

@Slf4j
@RequiredArgsConstructor(staticName="of")
@AllArgsConstructor(staticName="of")
@ToString
public class UserLombok {

    private Long id;

    private String name;

    private String phoneNo;

    private final String address;

    private String school;
    
    @Test
    public void test() {
        UserLombok userLombok1 = UserLombok.of("cc");
        UserLombok userLombok2 = UserLombok.of(2L, "hory", "155", "sh", "cc");

        log.info("userLombok toString:{}", userLombok1.toString());
        // userLombok toString:UserLombok(id=null, name=null, phoneNo=null, address=cc, school=null)
        
        log.info("userLombok toString:{}", userLombok2.toString());
        // userLombok toString:UserLombok(id=2, name=hory, phoneNo=155, address=sh, school=cc)
    }
}

注意:

  • 当我们没有指定构造器时,Java 编译器会自动生成一个没有任何参数的构造器,但是如果我们自己写了构造器之后,Java 就不会自动帮我们补上那个无参数的构造器了。
  • 然而很多地方(像是 Spring Data JPA),会需要每个类都一定要有一个无参数的构造器,所以在加上 @AllArgsConstructor 时,一定要补上 @NoArgsConstrcutor
  • @AllArgsConstructor@NoArgsConstrcutor是可以共用的

@Value

也是整合包,但是它会把所有的变量都设成 final 的,其他的就跟 @Data 一样,等于同时加了以下注解

  • @Getter(注意没有setter)
  • @ToString
  • @EqualsAndHashCode
  • @RequiredArgsConstructor

@Data 适合用在 POJO 或 DTO 上,而这个 @Value 注解,则是适合加在值不希望被改变的类上,像是某个类的值当创建后就不希望被更改,只希望我们读它而已,就适合加上 @Value 注解,也就是 @Value for immutable class

注意:此 lombok 的注解 @Value 和另一个 Spring 的注解 @Value 撞名,在 import 时不要 import 错了

@Builder

自动生成流式 set 值写法,从此之后再也不用写一堆 setter 了.

public class User {
    private Integer id;
    private String name;
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public void setName(String name) {
        this.name = name;
    }
}

public static void main(String[] args) {
    User user = new User();
    user.setId(1);
    user.setName("John");
}

等同于下面的写法

@Builder
public class User {
    private Integer id;
    private String name;
}

public static void main(String[] args) {
    User user = User.builder().id(1).name("John").build();
}

注意:虽然只要加上 @Builder 注解,就能够用流式写法快速设定对象的值,但 setter 还是必须要写不能省略的,因为 Spring 或是其他框架有很多地方都会用到对象的 getter/setter 对它们取值/赋值。

所以通常是 @Data 和 @Builder 会一起用在同个类上,既方便我们流式写代码,也方便框架做事。

@SneakyThrows

https://www.cnblogs.com/acmaner/p/13967688.html

自动抛受检异常,而无需显式在方法上使用 throws 语句

publicclass ThrowsTest {
    
    @SneakyThrows()
    public void read() {
        InputStream inputStream = new FileInputStream("");
    }
    @SneakyThrows
    public void write() {
        throw new UnsupportedEncodingException();
    }
    
    // 相当于
    public void read() throws FileNotFoundException {
        InputStream inputStream = new FileInputStream("");
    }
    public void write() throws UnsupportedEncodingException {
        throw new UnsupportedEncodingException();
    }
}

@Synchronized

用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性 或LOCK

而 Java 中的 synchronized 关键字锁对象是 this,锁在 this 或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁 this 或者类对象,这可能会导致竞争条件或者其它线程错误

public class SynchronizedDemo {
    @Synchronized
    public static void hello() {
        System.out.println("world");
    }
    
    // 相当于
    private static final Object $LOCK = new Object[0];
    public static void hello() {
        synchronized ($LOCK) {
            System.out.println("world");
        }
    }
}

@Getter(lazy=true)

可以替代经典的 Double Check Lock 样板代码

public class GetterLazyExample {
    
    @Getter(lazy = true)
    private final double[] cached = expensive();
    
    private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.asin(i);
        }
        return result;
    }
}

相当于

import java.util.concurrent.atomic.AtomicReference;

public class GetterLazyExample {
    
    private final AtomicReference<java.lang.Object> cached = new AtomicReference<>();
    
    public double[] getCached() {
        java.lang.Object value = this.cached.get();
        if (value == null) {
            synchronized (this.cached) {
                value = this.cached.get();
                if (value == null) {
                    final double[] actualValue = expensive();
                    value = actualValue == null ? this.cached : actualValue;
                    this.cached.set(value);
                }
            }
        }
        return (double[]) (value == this.cached ? null : value);
    }
    
    private double[] expensive() {
        double[] result = new double[1000000];
        for (int i = 0; i < result.length; i++) {
            result[i] = Math.asin(i);
        }
        return result;
    }
}

@Log

@Log:根据不同的注解生成不同类型的 log 对象,但是实例名称都是 log,有六种可选实现类

  • @CommonsLog Creates log = org.apache.commons.logging.LogFactory.getLog(LogExample.class)
  • @Log Creates log = java.util.logging.Logger.getLogger(LogExample.class.getName())
  • @Log4j Creates log = org.apache.log4j.Logger.getLogger(LogExample.class)
  • @Log4j2 Creates log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class)
  • @Slf4j Creates log = org.slf4j.LoggerFactory.getLogger(LogExample.class)
  • @XSlf4j Creates log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class)

@Slf4j

自动生成该类的 log 静态常量,要打日志就可以直接打,不用再手动 new log 静态常量了

public class User {
    private static final Logger log = LoggerFactory.getLogger(User.class);
    
    public static void main(String[] args) {
    	log.info("hello");
	}
}

等同于下面的写法

@Slf4j
public class User {
    public static void main(String[] args) {
    	log.info("hello");
	}
}

除了 @Slf4j 之外,lombok 也提供其他日志框架的变种注解可以用,像是 @Log、@Log4j…等,它们都是帮我们创建一个静态常量 log,只是使用的库不一样而已.

@Log

import java.util.logging.Logger;

@Log
private static final Logger log = Logger.getLogger(LogExample.class.getName());

@Log4j

import org.apache.log4j.Logger;

@Log4j
private static final Logger log = Logger.getLogger(LogExample.class);

log 系列注解最常用的就是 @Slf4j,SpringBoot 默认支持的就是 slf4j + logback 的日志框架,所以也不用再多做啥设定,直接就可以用在 SpringBoot project上.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Lombok 注解及实例大全 的相关文章

随机推荐

  • 19年11月最新Win10 LTSC系统封装部署教程(超详细)

    写在前面 在本着认真负责 不交差 不敷衍的情况下 尽可能详细的描述整个过程 本文的经验方法大多数来自于网上朋友们的无私分享 在实际操作中遇到的坑我会在下文中进行标注 有任何意见或疑问欢迎留言讨论 感谢平台提供一个舒适的交流环境 v 0 15
  • (差分)曼彻斯特编码及NRZ

    曼彻斯特编码 Manchester Encoding 也叫做相位 编码 Phase Encode 简写PE 是一个同步时钟编码技术 被 物理层使用来编码一个同步位流的时钟和数据 它在 以太网媒介系统中的应用属于数据通信中的两种位同步方法里的
  • 【const】与指针、数组、结构体的使用

    目录 指针与数组 指针与const const const的作用 const int 与 int const const的错误使用 const char arr和char arr 10 的区别 结构体与const 指针与数组 指针可访问数组
  • vue3.0 PC端自适应不同分辨率电脑

    使用rem单位去做页面的适配 先来了解一下什么是rem rem是CSS3新增的一个相对单位 root em 根em 我们可以通过去设定X rem Y px x和y为自定义数值 如图设定1rem 10px 第一步 安装相应的依赖为我们自动将全
  • Masked Autoencoders Are Scalable Vision Learners(屏蔽自编码器是可扩展的视觉学习器)--文献翻译和笔记

    论文链接 2111 06377 Masked Autoencoders Are Scalable Vision Learners arxiv org 论文标题 Masked Autoencoders Are Scalable Vision
  • Entity Framework中使用SQLite的一些问题

    SQLite数据相当的不错 我目前在一些小型网站都用这个数据库来取代Access 下面就是关于在ASP NET的Entity Framework当中使用SQLite的一些经验和一些小问题的解决办法 想要在ASP NET中使用SQLite 首
  • js md5 解密_JS逆向小结(开始)

    最近想研究一下JS逆向的相关知识 先分享一篇大佬的小总结 明天正式开搞 1 我的逆向分析流程 对于js逆向来说 基本遵循一个简单的流程 我是先进行刷新网页进行抓包 找到自己的目标请求 大部分时候是一个 但是有时回事多个 先前返回的数据可能在
  • 【Linux】Linux常用快捷键

    前言 由于需要 梳理了一下常用的快捷键 以便忘记时查找 Linux系统快捷键 Bash解释器 1 Tab键 补齐命令 补齐路径 显示当前目录下的所有目录 2 清屏 clear Ctrl L L 大小写均可 3 中断 暂停进程 ctrl c
  • bmFont的使用方法

    1 打开 bmfont exe 2 字体设置 选择 Font settings 在这里我们选择微软雅黑 微软雅黑支持中文 字符编码 选择 Unicode 你还可以在 Font settings 对话框里进行字体大小 字体平滑程度等设置 3
  • Qt开发教程:实现全屏显示

    Qt开发教程 实现全屏显示 在Qt开发中 有时候需要让程序窗口全屏显示 以提升用户体验 本教程将介绍如何使用Qt实现全屏显示 设置窗口属性 在Qt中 我们可以通过设置窗口属性来控制窗口显示方式 在此之前 我们需要在 pro文件中添加以下代码
  • IDEA中用java建库、建表、插入、打印的方法

    数据库 mysql 连接方式 jdbc 文件组织结构 create db java package jdbc import java sql public class create db 建立数据库连接 并创建一个新数据库 按照传入的参数
  • Sourcetree连接远程仓库需要登陆,但是一直登陆不上的问题解决方法

    授权类型选用 基础 只需要登陆你用户名和密码 将https作为首选协议 连接成功后可改ssh
  • 机器学习大作业---文献综述

    机器学习大作业 文献综述 机器学习技术在材料化学预测方面最新应用综述 怎么写综述 摘抄自https www zhihu com question 303494762 answer 555476024 文献综述和综述论文是有区别的 文献综述可
  • 飞天平台安全相关

    飞天平台安全相关 1 capability机制 用户的身份认证 authentication 是基于密钥机制的 用户对资源的访问控制是基于权能 capability 机制进行授权 authorization 的 capability是用于访
  • c++入门系列(二)之标识符

    什么是标识符 标识符是指用来标识某个实体的一个符号 在不同的应用环境下有不用的含义 这句话相当于废话 在计算机编程语言中 标识符是用户编程时使用的名字 用于给变量 常量 函数 语句块等命名 以建立起名称与使用之间的关系 通俗的话说 标识符是
  • 模式识别课程:目标检测②传统检测算法

    title 目标检测 传统检测算法 目标检测实验报告 检测所用软硬件 云服务器 硬件 macOS或者windows电脑 软件 pycharm 生成的测试集 云服务器 滴滴云 https www didiyun com activity ht
  • ##清理memcached缓存

    清理memcached缓存 连接 telnet 127 0 0 1 8088 flush all quit 重启下脚本就可以生效了 ps ef grep mem kill 进程PID 重启脚本 etc init d memcached st
  • 时序区间预测

    文章目录 效果一览 文章概述 部分源码 参考资料 效果一览 文章概述 基于高斯过程回归 GPR 时间序列区间预测 matlab代码 单变量输入模型 基于高斯过程回归 GPR 时间序列区间预测 matiab代码 单变量输入模型 评价指标包括
  • 2023年有哪些值得推荐的深度学习书?

    深度学习指的是用一种特定的方法来解决一些机器学习的问题 这种方法的中心思想是 基于一系列的离散的层 layer 构建机器学习算法 如果将这些层 垂直堆叠 就说这个结果是有深度 depth 的 或者说算法是有深度的 构建深度网络的方法有很多种
  • Lombok 注解及实例大全

    Project Lombok是一个java库 它可以自动插入到编辑器和构建工具中 为Java增添趣味 永远不要再编写另一个getter或equals方法 只要有一个注释 你的类就有一个功能齐全的构建器 自动化你的日志变量 等等 val 用在