当前位置:

首页 > 编程开发 > Java库lombok及注解如何使用

Java库lombok及注解如何使用

Lombok是什么Lombok是一个旨在减少代码开发工作的Java库。它提供了一些简单的注解,并以此来消除java中臃肿的模版代码,比如pojo中最常见的setter/getter方法,比如toString方法,比如equals方法等等,还可以帮助我们关闭流,即使JDK7中已经有了TWR特性,但这个包很值得一试。通过几个简单的注解,将模版代码在编译时写入程序。使用eclipse可以在Outline窗口看到生成的方法,但是在源码里是干净的.安装首先去lombok官网下载jar包。只是把jar包下载下来并导入

本文目录

    Lombok是什么

    Lombok是一个旨在减少代码开发工作的Java库。它提供了一些简单的注解,并以此来消除java中臃肿的模版代码,比如 pojo 中最常见的 setter/getter 方法, 比如 toString 方法, 比如 equals 方法等等,还可以帮助我们关闭流,即使 JDK7 中已经有了 TWR 特性,但这个包很值得一试。

    通过几个简单的注解,将模版代码在编译时写入程序。使用 eclipse 可以在 Outline 窗口看到生成的方法,但是在源码里是干净的.

    安装

    首先去 lombok 官网下载jar 包。

    只是把 jar 包下载下来并导入工程中,会发现 IDE 不识别它的注解,那怎么办?

    对于eclipse

    将 lombok.jar 复制到 eclipse.ini 所在的目录下,然后编辑 eclipse.ini 文件, 在它的末尾插入以下两行并保存:

    Xbootclasspath/a:lombok.jar
    javaagent:lombok.jar

    接着重启 eclipse 就可以愉快地使用这个库了。

    对于 IDEA

    在 IntelliJ 的插件中心可以找到它。

    QuickStart

    Lombok 提供的注解不多,但都好用,简要说一下常用的几个。

    @Setter/@Getter

    这两个注解修饰成员变量,可用于生成 setter/gettter 模版代码。
    举个栗子:

    import lombok.AccessLevel;
    import lombok.Getter;
    import lombok.Setter;
    public class Student {
        @Setter @Getter private String name;
        @Getter(AccessLevel.PROTECTED) private int age;// 可以指定访问权限
        @Setter @Getter private String[] hobbies;
    }

    将字节码文件反编译后可以看到下面这段代码

    public class Student {
      private String name;
      private int age;
      private String[] hobbies;
      public String getName() { return this.name; } 
      public void setName(String name) { this.name = name; }
      protected int getAge() { return this.age; }
      public String[] getHobbies() { return this.hobbies; } 
      public void setHobbies(String[] hobbies) { this.hobbies = hobbies; }
    }

    @ToString

    import lombok.ToString;
    @ToString(exclude="id")
    public class ToStringExample {
        private int id;
        private String name;
        private String[] tags;
    }

    编译后

    import java.util.Arrays;
    public class ToStringExample {
      public String toString() { 
        return "ToStringExample(name=" + this.name + ", tags=" + Arrays.deepToString(this.tags) + ")"; 
      }
      private int id;
      private String name;
      private String[] tags;
    }

    我们发现,对于数组,在写 toString 方法时使用了 Arrays类的 静态方法 deepToString。

    来看 eclipse 自动生成的 toString 方法:

    @Override
    public String toString() {
        return "ToStringExample [name=" + name + ", tags=" + Arrays.toString(tags) + "]";
    }

    eclipse 中对于数组采用的是 Arrays.toString()。

    区别:这两个方法的区别是这样的,对于多维数组,使用 toString 只能打印出内部数组的名字,这时需要使用 deepToString 方法,它能将内部数组的内容全部打印出来。

    exclude 参数

    可以指定哪些属性不出现在 toString 方法中, 比如 exclude={"id", "name"}

    doNotUseGetters 参数

    当类中有成员变量的 getter 方法时,生成 toString 方法会使用这些 getter 方法,比如

    public String toString() { 
        return "ToStringExample(name=" + getName() + ", tags=" + Arrays.deepToString(getTags()) + ")"; 
    }

    但是将该参数设置为 true 时(默认为 false),生成 toString 方法时就不会使用 getter 方法,而是直接使用这些成员变量,比如

    public String toString() { 
        return "ToStringExample(name=" + this.name + ", tags=" + Arrays.deepToString(this.tags) + ")"; 
    }

    includeFieldNames参数

    原本是以 fieldName = fieldValue 的格式来生成 toString 方法的,但是将该参数设置为 false 后(默认是 true),就不会显示 fieldName 了,而只是生成 fieldValue, 比如

    public String toString() { 
      return "ToStringExample(" + getId() + ", " + getName() + ", " + Arrays.deepToString(getTags()) + ")"; 
    }

    callSuper 参数

    若类 A 是类 B 的子类,那么在 A 类重写 toString 时,若把该参数设置为 true,会加入下面这段代码,即也会把父类 B 的 toString 也写入。

    super=" + super.toString()

    @NonNull

    检查传入对象是否为 Null,若为null,则抛出NullPointerException异常。
    举个栗子

    import lombok.NonNull;
    public class NonNullExample extends Student{
        private String name;
        public NonNullExample(@NonNull Student student) {
            this.name = student.getName();
        }
    }

    编译后代码

    import lombok.NonNull;
    public class NonNullExample extends Student { 
        private String name;
        public NonNullExample(@NonNull Student student) { 
            if (student == null) 
                throw new NullPointerException("student");
            this.name = student.getName();
      }
    }

    @EqualsAndHashCode

    用在类上,用于生成 equals 和 hashcode 方法。
    举个栗子

    @EqualsAndHashCode(exclude={"id"})
    public class EqualsAndHashCodeExample {
         private transient int transientVar = 10;
         private String name;
         private double score;
         private String[] tags;
         private int id;
    }

    编译后代码

    import java.util.Arrays;
    public class EqualsAndHashCodeExample { 
        public int hashCode() { 
            int PRIME = 59;
            int result = 1;
            Object $name = this.name;
            result = result * 59 + ($name == null ? 43 : $name.hashCode());
            long $score = Double.doubleToLongBits(this.score);
            result = result * 59 + (int)($score ^ $score >>> 32);
            result = result * 59 + Arrays.deepHashCode(this.tags);
            return result; 
        } 
        protected boolean canEqual(Object other) { 
            return other instanceof EqualsAndHashCodeExample; 
        } 
        public boolean equals(Object o) { 
            if (o == this)  return true; 
            if (!(o instanceof EqualsAndHashCodeExample)) return false; 
            EqualsAndHashCodeExample other = (EqualsAndHashCodeExample)o; 
            if (!other.canEqual(this)) return false; 
            Object this$name = this.name;
            Object other$name = other.name; 
            if (this$name == null ? other$name != null : !this$name.equals(other$name)) 
                return false; 
            if (Double.compare(this.score, other.score) != 0) 
                return false; 
            return Arrays.deepEquals(this.tags, other.tags);
        }
    private transient int transientVar = 10;
    private String name;
    private double score;
    private String[] tags;
    private int id;
    }

    可以看出transient修饰的变量,不会参与。

    参数

    参数 of 用来指定参与的变量,其他的跟 @ToString 注解类似。

    @Data

    该注解用于修饰类,会自动生成getter/setter方法, 以及重写equals(), hashcode()和toString()方法。

    @Cleanup

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

    举个栗子:

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

    @NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor

    这三个注解修饰在类上。

    @NoArgsConstructor 用于生成一个无参构造方法。

    @RequiredArgsConstructor 会生成一个包含了被@NotNull标识的变量的构造方法。同样可以设置生成构造方法的权限,使用 access参数进行设置。

    @AllArgsConstructor 会生成一个包含所有变量, 同时如果变量使用了@NotNull,会进行是否为空的校验。

    举个栗子:

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

    这与下面这段代码是等价的,

    import java.beans.ConstructorProperties;
    public class ConstructorExample { 
        public static ConstructorExample of(@lombok.NonNull String desc) { 
            return new ConstructorExample(desc); 
        } 
        private ConstructorExample(@lombok.NonNull String desc) {
            if (desc == null) throw new NullPointerException("desc"); 
            this.desc = desc; 
        } 
        @ConstructorProperties({"x", "y", "desc"})
        protected ConstructorExample(int x, int y, @lombok.NonNull String desc) {
            if (desc == null) throw new NullPointerException("desc"); 
            this.x = x;
            this.y = y;
            this.desc = desc;
        }
        private int x;
        private int y;
        @lombok.NonNull
        private String desc;
        public class NoArgsExample
        {
            private String field;
            public NoArgsExample() {}
        }
    }

    @Value

    该注解用于修饰类,是@Data的不可变形式, 相当于为成员变量添加final声明, 只提供getter方法, 而不提供setter方法,然后还有 equals/hashCode/toString方法,以及一个包含所有参数的构造方法。

    @builder

    用在类、构造器、方法上,为你提供复杂的builder APIs,让你可以像如下方式调用

    Person.builder().name("A
    dam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build()

    举个栗子:

    import lombok.Builder;
    import java.util.Set;
    @Builder
    public class BuilderExample {
        private String name;
        private int age;
    }

    反编译代码如下:

    package tutorial.lombok;
        public class BuilderExample
        {
            public static class BuilderExampleBuilder
            {
                private String name;
                private int age;
                public BuilderExampleBuilder name(String name)
                {
                    this.name = name;
                    return this;
                }
                public BuilderExampleBuilder age(int age)
                {
                    this.age = age;
                    return this;
                }
                public BuilderExample build()
                {
                    return new BuilderExample(name, age);
                }
                public String toString()
                {
                    return (new StringBuilder()).append("BuilderExample.BuilderExampleBuilder(name=").append(name).append(", age=").append(age).append(")").toString();
                }
                BuilderExampleBuilder()
                {
                }
            }
            private String name;
            private int age;
            BuilderExample(String name, int age)
            {
                this.name = name;
                this.age = age;
            }
            public static BuilderExampleBuilder builder()
            {
                return new BuilderExampleBuilder();
            }
        }

    注意:

    使用@Singular注解的集合属性名必须使用s结尾, lombok会将属性名结尾的s去掉,剩余的名字会作为方法名, 向这个集合中添加元素。

    @Builder 的参数builderClassName设置生成的builder方法名,buildMethodName 设置build方法名,builderMethodName设置builderMethod`方法名。
    比如

    @Builder(builderClassName = "GBuilder", buildMethodName = "buildG", builderMethodName = "GBuilder"

    @SneakyThrows

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

    @Synchronized

    用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性 LOCK,而java中的synchronized关键字锁对象是this,锁在this或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁this或者类对象,这可能会导致竞争条件或者其它线程错误。

    举个栗子:

    import lombok. Synchronized;
    public class SynchronizedExample {
        private final Object readLock = new Object() ;
        @Synchronized
        public static void hello() {
            System. out. println("world") ;
        }
        @Synchronized("readLock")
        public void foo() {
            System. out. println("bar") ;
        }
    }

    反编译代码如下:

    public class SynchronizedExample {
        private static final Object $LOCK = new Object[0] ;
        private final Object readLock = new Object() ;
        public static void hello() {
            synchronized($LOCK) {
                System. out. println("world") ;
            }
        }
        public int answerToLife() {
            synchronized($lock) {
                return 42;
            }
        }
        public void foo() {
            synchronized(readLock) {
                System. out. println("bar") ;
            }
        }
    }

    @Getter(lazy=true)

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

    举个栗子:

    import lombok.Getter;
    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 cached = new AtomicReference();
        public GetterLazyExample()
        {
        }
        private double[] expensive()
        {
                double result[] = new double[0xf4240];
            for (int i = 0; i < result.length; i++)
                result[i] = Math.asin(i);
            return result;
        }
        public double[] getCached()
        {
            Object value = cached.get();
            if (value == null)
                synchronized (cached)
                {
                    value = cached.get();
                    if (value == null)
                    {
                        double actualValue[] = expensive();
                        value = actualValue != null ? ((Object) (actualValue)) : ((Object) (cached));
                        cached.set(value);
                    }
                }
            return (double[])(double[])(value != cached ? value : null);
        }
    }

    @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) ;

    举个栗子,

    import lombok.extern.java.Log;
    import lombok.extern.slf4j.Slf4j;
    @Log
    public class LogExample {
        public static void main(String... args) {
            log.error("Something's wrong here");
        }
    }
    @Slf4j
    public class LogExampleOther {
        public static void main(String... args) {
            log.error("Something else is wrong here");
        }
    }
    @CommonsLog(topic="CounterLog")
    public class LogExampleCategory {
        public static void main(String... args) {
            log.error("Calling the 'CounterLog' with a message");
        }
    }
    @CommonsLog(topic="CounterLog")

    这条语句会翻译成这样

    private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。