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日志并进行多维度分析。
目录
相关文章
|
2月前
|
存储 缓存 安全
Java内存模型深度解析:从理论到实践####
【10月更文挑战第21天】 本文深入探讨了Java内存模型(JMM)的核心概念与底层机制,通过剖析其设计原理、内存可见性问题及其解决方案,结合具体代码示例,帮助读者构建对JMM的全面理解。不同于传统的摘要概述,我们将直接以故事化手法引入,让读者在轻松的情境中领略JMM的精髓。 ####
44 6
|
2月前
|
设计模式 Java 开发者
Java中的异常处理:理解与实践
【10月更文挑战第42天】在Java的世界中,异常处理是每个开发者必须面对的挑战。它就像是一场不可预知的风暴,可能会在任何时候突然降临,打乱我们的计划。但是,如果我们能够掌握正确的处理方法,这场风暴也可以变成推动我们前进的力量。本文将带你深入理解Java中的异常处理机制,通过代码示例,我们将一起学习如何捕获、处理和预防异常,让你的程序在面对任何挑战时都能保持稳健和优雅。
|
2月前
|
Arthas 监控 Java
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
本文介绍了阿里云 Java Agent 4.x 版本在基于 OTel Java Agent 二次开发过程中的实践与思考,并重点从功能、性能、稳定性、兼容性四个方面介绍了所做的工作。同时也介绍了阿里云可观测团队积极参与开源建设取得的丰厚成果。
251 6
拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
|
1月前
|
存储 监控 小程序
Java中的线程池优化实践####
本文深入探讨了Java中线程池的工作原理,分析了常见的线程池类型及其适用场景,并通过实际案例展示了如何根据应用需求进行线程池的优化配置。文章首先介绍了线程池的基本概念和核心参数,随后详细阐述了几种常见的线程池实现(如FixedThreadPool、CachedThreadPool、ScheduledThreadPool等)的特点及使用场景。接着,通过一个电商系统订单处理的实际案例,分析了线程池参数设置不当导致的性能问题,并提出了相应的优化策略。最终,总结了线程池优化的最佳实践,旨在帮助开发者更好地利用Java线程池提升应用性能和稳定性。 ####
|
1月前
|
安全 Java 数据库连接
Java中的异常处理:理解与实践
在Java的世界里,异常处理是维护代码健壮性的守门人。本文将带你深入理解Java的异常机制,通过直观的例子展示如何优雅地处理错误和异常。我们将从基本的try-catch结构出发,探索更复杂的finally块、自定义异常类以及throw关键字的使用。文章旨在通过深入浅出的方式,帮助你构建一个更加稳定和可靠的应用程序。
34 5
|
2月前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
177 6
|
1月前
|
安全 Java 程序员
Java内存模型的深入理解与实践
本文旨在深入探讨Java内存模型(JMM)的核心概念,包括原子性、可见性和有序性,并通过实例代码分析这些特性在实际编程中的应用。我们将从理论到实践,逐步揭示JMM在多线程编程中的重要性和复杂性,帮助读者构建更加健壮的并发程序。
|
2月前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
72 1
|
2月前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
61 2