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

源码共读

共 16986字,需浏览 34分钟

 ·

2021-04-11 22:22

👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

作者丨浅羽Eric

来源丨浅羽的IT小屋


前言

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

1. Lombok的概念

「概念:」

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

2、Lombok的安装

「安装步骤:」

  • 在IDEA的插件Plugins中搜索Lombok


  • 安装Lombok

「注意:」

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

浏览 7
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报