简化开发|Lombok神器带你消除冗余代码

简介: Lombok是一款Java开发插件,使得Java开发者可以通过其定义的一些注解来消除业务过程中冗余的代码,尤其是简单的Java模型对象(POJO)。而当我们如果在开发环境中使用Lom...

 

网络异常,图片无法展示
|
image.gif

image.gif

前言

Lombok是一款Java开发插件,使得Java开发者可以通过其定义的一些注解来消除业务过程中冗余的代码,尤其是简单的Java模型对象(POJO)。而当我们如果在开发环境中使用Lombok开发插件后,可以省出重复构建,诸如hashCode和equals这样的方法以及各种业务对象模型的accessor和ToString等方法的大量时间。对于这些方法,它能够在编译源代码期间自动帮我们生产这些方法,并没有如反射那样降低程序的性能。本文将带大家详细介绍关于Lombok的使用以及原理。

公众号:「浅羽的IT小屋」

1. Lombok的概念

「概念:」

    • Lombok是一种Java实用工具,可以用来帮助开发人员消除冗余的代码,对于一些简单的Java对象(POJO),它通过注释实现这一目的。

    2、Lombok的安装

    「安装步骤:」

      • 在IDEA的插件Plugins中搜索Lombok

      网络异常,图片无法展示
      |
      image.gif

        • 安装Lombok

        网络异常,图片无法展示
        |
        image.gif

        「注意:」

          • 在使用Lombok注解的时候记得要导入Lombok.jar包到工程,Maven Project的话,要在pom.xml中添加依赖
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>1.16.8</version>
          </dependency>

          image.gif

          3、Lombok注解说明

          「常用注解:」

          Lombok注解说明
          * val:用在局部变量前面,相当于将变量声明为final
          * @NonNull:给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出NPE(NullPointerException)
          * @Cleanup:自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成try-finally这样的代码来关闭流
          * @Getter/@Setter:用在属性上,再也不用自己手写setter和getter方法了,还可以指定访问范围
          * @ToString:用在类上,可以自动覆写toString方法,当然还可以加其他参数,例如@ToString(exclude=”id”)排除id属性,或者@ToString(callSuper=true, includeFieldNames=true)调用父类的toString方法,包含所有属性
          * @EqualsAndHashCode:用在类上,自动生成equals方法和hashCode方法
          * @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor:用在类上,自动生成无参构造和使用所有参数的构造函数以及把所有@NonNull属性作为参数的构造函数,如果指定staticName = “of”参数,同时还会生成一个返回类对象的静态工厂方法,比使用构造函数方便很多
          * @Data:注解在类上,相当于同时使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstrutor这些注解,对于POJO类十分有用
          * @Value:用在类上,是@Data的不可变形式,相当于为属性添加final声明,只提供getter方法,而不提供setter方法
          * @Builder:用在类、构造器、方法上,为你提供复杂的builder APIs,让你可以像如下方式一样调用Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();更多说明参考Builder
          * @SneakyThrows:自动抛受检异常,而无需显式在方法上使用throws语句
          * @Synchronized:用在方法上,将方法声明为同步的,并自动加锁,而锁对象是一个私有的属性$lock或$LOCK,而java中的synchronized关键字锁对象是this,锁在this或者自己的类对象上存在副作用,就是你不能阻止非受控代码去锁this或者类对象,这可能会导致竞争条件或者其它线程错误
          * @Getter(lazy=true):可以替代经典的Double Check Lock样板代码
          * @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);

          image.gif

          4、Lombok代码示范

          「代码示例:」

            • val将变量声明final类型
            public static void main(String[] args) {
                val sets = new HashSet<String>();
                val lists = new ArrayList<String>();
                val maps = new HashMap<String, String>();
                //=>相当于如下
                final Set<String> sets2 = new HashSet<>();
                final List<String> lists2 = new ArrayList<>();
                final Map<String, String> maps2 = new HashMap<>();
            }

            image.gif

              • @Nonnull为方法和构造函数的参数提供非空检查
              public void notNullExample(@NonNull String string) {
                  string.length();
              }
              //=>相当于
              public void notNullExample(String string) {
                  if (string != null) {
                      string.length();
                  } else {
                      throw new NullPointerException("null");
                  }
              }

              image.gif

                • @Cleanup自动释放资源
                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();
                            }
                        }
                    }
                }

                image.gif

                  • @Getter/@Setter对类的属性字段自动生成Get/Set方法
                  @Setter(AccessLevel.PUBLIC)
                  @Getter(AccessLevel.PROTECTED)
                  private int id;
                  private String shap;

                  image.gif

                    • @ToString为类生成一个toString方法
                    @ToString(exclude = "id", callSuper = true, includeFieldNames = true)
                    public class 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());
                        }
                    }

                    image.gif

                      • @EqualsAndHashCode为类生成equals和hasCode方法
                      @EqualsAndHashCode(exclude = {"id", "shape"}, callSuper = false)
                      public class LombokDemo {
                          private int id;
                          private String shap;
                      }

                      image.gif

                        • @NoArgsConstructor,@RequiredArgsConstructor and @AllArgsConstructor,分别为类自动生成无参构造,指定参数构造器和包含所有参数构造器
                        @NoArgsConstructor
                        @RequiredArgsConstructor(staticName = "of")
                        @AllArgsConstructor
                        public class LombokDemo {
                            @NonNull
                            private int id;
                            @NonNull
                            private String shap;
                            private int age;
                            public static void main(String[] args) {
                                new LombokDemo(1, "circle");
                                //使用静态工厂方法
                                LombokDemo.of(2, "circle");
                                //无参构造
                                new LombokDemo();
                                //包含所有参数
                                new LombokDemo(1, "circle", 2);
                            }
                        }

                        image.gif

                          • @Data在类上使用,相当于同时使用@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstructor这些注解
                          import lombok.Data;
                          @Data
                          public class Menu {
                              private String shopId;
                              private String skuMenuId;
                              private String skuName;
                              private String normalizeSkuName;
                              private String dishMenuId;
                              private String dishName;
                              private String dishNum;
                              //默认阈值
                              private float thresHold = 0;
                              //新阈值
                              private float newThresHold = 0;
                              //总得分
                              private float totalScore = 0;
                          }

                          image.gif

                            • @Value为属性添加final声明
                            @Value
                            public class LombokDemo {
                                @NonNull
                                private int id;
                                @NonNull
                                private String shap;
                                private int age;
                                //相当于
                                private final int id;
                                public int getId() {
                                    return this.id;
                                }
                                ...
                            }

                            image.gif

                              • @Builder提供构建值对象方式
                              @Builder
                              public class BuilderExample {
                                  private String name;
                                  private int age;
                                  @Singular
                                  private Set<String> occupations;
                                  public static void main(String[] args) {
                                      BuilderExample test = BuilderExample.builder().age(11).name("test").build();
                                  }
                              }

                              image.gif

                                • @SneakyThrows自动抛受检异常
                                import lombok.SneakyThrows;
                                import java.io.FileInputStream;
                                import java.io.FileNotFoundException;
                                import java.io.InputStream;
                                import java.io.UnsupportedEncodingException;
                                public class Test {
                                    @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();
                                    }
                                }

                                image.gif

                                  • @Synchronized将方法声明同步并自动加锁
                                  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");
                                          }
                                      }
                                  }

                                  image.gif

                                    • @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;
                                        }
                                    }

                                    image.gif

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

                                      image.gif

                                      结语

                                      本篇关于Lombok的介绍就先到这里结束了,后续会出更多关于Lombok系列更多文章,谢谢大家支持!

                                      image.gif


                                      相关文章
                                      |
                                      9天前
                                      |
                                      移动开发 前端开发 Java
                                      Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
                                      JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
                                      Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
                                      |
                                      1月前
                                      |
                                      Java 开发者 微服务
                                      Spring Boot 入门:简化 Java Web 开发的强大工具
                                      Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
                                      58 6
                                      Spring Boot 入门:简化 Java Web 开发的强大工具
                                      |
                                      11天前
                                      |
                                      安全 Java 编译器
                                      深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
                                      `synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
                                      33 3
                                      |
                                      20天前
                                      |
                                      存储 JavaScript 前端开发
                                      基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
                                      一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
                                      101 13
                                      |
                                      25天前
                                      |
                                      算法 Java API
                                      如何使用Java开发获得淘宝商品描述API接口?
                                      本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
                                      56 10
                                      |
                                      18天前
                                      |
                                      前端开发 Java 测试技术
                                      java日常开发中如何写出优雅的好维护的代码
                                      代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
                                      54 2
                                      |
                                      28天前
                                      |
                                      JavaScript 安全 Java
                                      java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
                                      基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
                                      |
                                      1月前
                                      |
                                      安全 Java API
                                      Java中的Lambda表达式:简化代码的现代魔法
                                      在Java 8的发布中,Lambda表达式的引入无疑是一场编程范式的革命。它不仅让代码变得更加简洁,还使得函数式编程在Java中成为可能。本文将深入探讨Lambda表达式如何改变我们编写和维护Java代码的方式,以及它是如何提升我们编码效率的。
                                      |
                                      8天前
                                      |
                                      Java
                                      Java—多线程实现生产消费者
                                      本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
                                      Java—多线程实现生产消费者
                                      |
                                      10天前
                                      |
                                      安全 Java Kotlin
                                      Java多线程——synchronized、volatile 保障可见性
                                      Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。