Lombok高效实践

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Lombok 是一种Java 实用工具,可以帮助开发人员消除冗长的重复代码,尤其是对于简单的 Java 对象。它在代码编译阶段就会自动生成相应的代码,所以对性能没有任何影响。


一、概述



Lombok 是一种Java 实用工具,可以帮助开发人员消除冗长的重复代码,尤其是对于简单的 Java 对象。它在代码编译阶段就会自动生成相应的代码,所以对性能没有任何影响。

Maven 项目中引入 Lombok:

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

然后在 IDE(IDEA、Eclipse 等)中安装 Lombok 插件。


二、特性



类型 作用 备注
val 定义 final 本地局部变量 必须要初始化
var 定义本地局部变量 必须要初始化
@NonNull 定义非空检查
@Cleanup 自动关闭资源
@Getter/@Setter 定义 Getter/Setter 方法
@ToString 定义 toString 方法
@EqualsAndHashCode 定义 hashCodeequals 方法
@NoArgsConstructor 定义无参构造方法
@RequiredArgsConstructor 定义非空参数构造方法
@AllArgsConstructor 定义全参构造方法
@Data 包含 @ToString@Getter@Setter 等常用注解
@Builder 定义构造器
@SneakyThrows 定义异常捕获,省略 throws 操作
@Synchronized 定义同步锁
@Log 定义日志变量,支持 @Log4jSlf4j


三、实践



val

使用 val 可以定义一个本地局部变量,而不用指定该变量的类型,默认会使用 final 修饰,所以必须初始化。

public class Example {
    // Lombok
    public void lombok() {
        val str = "CodeArtist";
        val year = 2021;
        System.out.println(str);
        System.out.println(year);
    }
    // 原生Java
    public void example() {
        final String str = "CodeArtist";
        final int year = 2021;
        System.out.println(str);
        System.out.println(year);
    }
}

var

varval 功能一样,定义一个本地局部变量,只不过没有用 final 修饰,可以二次赋值,在使用的时候也需要初始化。

public class Example {
    // Lombok
    public void lombok() {
        var str = "CodeArtist";
        var year = 2021;
        System.out.println(str);
        System.out.println(year);
    }
    // 原生Java
    public void example() {
        String str = "CodeArtist";
        int year = 2021;
        System.out.println(str);
        System.out.println(year);
    }
}

@NonNull

@NonNull 可以作用在构造方法或其他方法的参数上,会在方法开头对参数添加一个非空检验,为空时抛出空指针异常。

public class Example {
    // Lombok
    public void lombok(@NonNull String name) {
        System.out.println(name);
    }
    // 原生Java
    public void example(String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            System.out.println(name);
        }
    }
}

@Cleanup

在定义一个资源前面添加 @Cleanup,可以使用完后自动调用 close() 方法来关闭资源。

public class Example {
    // Lombok
    public void lombok() throws Exception {
        @Cleanup InputStream in = new FileInputStream("path");
        byte[] b = new byte[10000];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
        }
    }
    // 原生Java
    public void example() throws Exception {
        InputStream in = new FileInputStream("path");
        try {
            byte[] b = new byte[10000];
            while (true) {
                int r = in.read(b);
                if (r == -1) break;
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
    }
}

@Getter/@Setter

使用 @Getter/@Setter 注解来生成类字段的 Getter 和 Setter 方法,它们也可以单独作用在字段上,来对生成某个字段 Getter 和 Setter 方法。

// Lombok
@Getter
@Setter
public class Example {
    private int age;
    private String name;
}
// 原生Java
public class Example {
    private int age;
    private String name;
    public int getAge() {
        return this.age;
    }
    public String getName() {
        return this.name;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void setName(String name) {
        this.name = name;
    }
}

@ToString

使用 @ToString 可以对字段生成 toString 方法,在打印日志的时候可以输出对象的字段值,也可以使用 @ToString.Exclude 注解来指定哪个字段不打印。

// Lombok
@ToString
public class Example {
    private int age;
    private String name;
}
// 原生Java
public class Example {
    private int age;
    private String name;
    public String toString() {
        return "Example(age=" + this.age + ", name=" + this.name + ")";
    }
}

@EqualsAndHashCode

使用 @EqualsAndHashCode 生成对象的 equals()hashCode() 方法,也可以使用 @EqualsAndHashCode.Exclude 注解来不包含某个字段。

// Lombok
@EqualsAndHashCode
public class Example {
    private int age;
    private String name;
}
// 原生Java
public class Example {
    private int age;
    private String name;
    public boolean equals(final Object o) {
        // 省略
        return true;
    }
    public int hashCode() {
        // 省略
        return 0;
    }
}

@ToString@EqualsAndHashCode 如果类中有继承的情况,可以在注解中定义 callSuper 来生成包含调用父类方法的代码。

@NoArgsConstructor

使用 @NoArgsConstructor 来生成无参构造方法。

// Lombok
@NoArgsConstructor
public class Example {
    private int age;
    private String name;
}
// 原生Java
public class Example {
    private int age;
    private String name;
    public Example() {
    }
}

@RequiredArgsConstructor

使用 @RequiredArgsConstructor 来生成含有必须需要初始化参数的参构造方法,比如 final 修饰的字段。

// Lombok
@RequiredArgsConstructor
public class Example {
    private final String name;
    private int age;
}
// 原生Java
public class Example {
    private int age;
    private final String name;
    public Example(String name) {
        this.name = name;
    }
}

@AllArgsConstructor

使用 @AllArgsConstructor 来生成含有所有参数的构造方法。

// Lombok
@AllArgsConstructor
public class Example {
    private String name;
    private int age;
}
// 原生Java
public class Example {
    private String name;
    private int age;
    public Example(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

生成构造方法的注解都可以通过 access 属性来指定构造方法的访问权限。

@Data

@Data 注解是定义实体类最常用的注解,它将常用的注解整合成一个,功能包括:

  • @Getter
  • @Setter
  • @ToString
  • @EqualsAndHashCode
  • @RequiredArgsConstructor
// Lombok
@Data
public class Example {
    private String name;
    private int age;
}
@Getter
@Setter
@ToString
@EqualsAndHashCode
@RequiredArgsConstructor
public class Example {
    private String name;
    private int age;
}

@Builder

@Builder 注解可以生成一个内部类来使用构造器设计模式来给 Java 对象赋值。

// Lombok
@Builder
public class Example {
    private String name;
    private int age;
}
// 原生Java
public class Example {
    private String name;
    private int age;
    Example(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public static ExampleBuilder builder() {
        return new ExampleBuilder();
    }
    public static class ExampleBuilder {
        private String name;
        private int age;
        ExampleBuilder() {
        }
        public ExampleBuilder name(String name) {
            this.name = name;
            return this;
        }
        public ExampleBuilder age(int age) {
            this.age = age;
            return this;
        }
        public Example build() {
            return new Example(name, age);
        }
        public String toString() {
            return "Example.ExampleBuilder(name=" + this.name + ", age=" + this.age + ")";
        }
    }
}

@SneakyThrows

@SneakyThrows 可以对编译时校验的异常进行捕获然后处理。

public class Example {
    // Lombok
    @SneakyThrows
    private void lombok() {
        TimeUnit.MINUTES.sleep(1);
    }
    // 原生Java
    private void example() {
        try {
            TimeUnit.MINUTES.sleep(1L);
        } catch (Throwable e) {
            throw Lombok.sneakyThrow(e);
        }
    }
}

@Synchronized

@Synchronized 可以给方法内部在代码加上 synchronized 同步锁。

public class Example {
    private final Object $lock = new Object[0];
    // Lombok
    @Synchronized
    private void lombok() {
        System.out.println("CodeArtist");
    }
    // 原生Java
    private void example() {
        synchronized (this.$lock) {
            System.out.println("CodeArtist");
        }
    }
}

@Log

@Log 可以在类中定义一个日志变量,它包括生成一系列日志框架的变量的注解,常用的有:

  • @Log
  • @Log4j
  • Slf4j
// Lombok
@Slf4j
public class Example {
}
// 原生Java
public class Example {
    private static final Logger log = org.slf4j.LoggerFactory.getLogger(Example.class);
}


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
1月前
|
设计模式 安全 Java
Java编程中的单例模式:理解与实践
【10月更文挑战第31天】在Java的世界里,单例模式是一种优雅的解决方案,它确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的实现方式、使用场景及其优缺点,同时提供代码示例以加深理解。无论你是Java新手还是有经验的开发者,掌握单例模式都将是你技能库中的宝贵财富。
39 2
|
9天前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
28天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
25天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
29天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
39 3
|
28天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
1月前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
107 10
|
1月前
|
Java 程序员 数据库连接
Java中的异常处理:理解与实践
【10月更文挑战第29天】在Java编程的世界里,异常像是不请自来的客人,它们可能在任何时候闯入我们的程序宴会。了解如何妥善处理这些意外访客,不仅能够保持我们程序的优雅和稳健,还能确保它不会因为一个小小的失误而全盘崩溃。本文将通过浅显易懂的方式,带领读者深入异常处理的核心概念,并通过实际示例展现如何在Java代码中实现有效的异常管理策略。
|
1月前
|
缓存 Java 调度
Java中的多线程编程:从基础到实践
【10月更文挑战第24天】 本文旨在为读者提供一个关于Java多线程编程的全面指南。我们将从多线程的基本概念开始,逐步深入到Java中实现多线程的方法,包括继承Thread类、实现Runnable接口以及使用Executor框架。此外,我们还将探讨多线程编程中的常见问题和最佳实践,帮助读者在实际项目中更好地应用多线程技术。
26 3
|
1月前
|
监控 安全 Java
Java多线程编程的艺术与实践
【10月更文挑战第22天】 在现代软件开发中,多线程编程是一项不可或缺的技能。本文将深入探讨Java多线程编程的核心概念、常见问题以及最佳实践,帮助开发者掌握这一强大的工具。我们将从基础概念入手,逐步深入到高级主题,包括线程的创建与管理、同步机制、线程池的使用等。通过实际案例分析,本文旨在提供一种系统化的学习方法,使读者能够在实际项目中灵活运用多线程技术。