Lombok的详细使用及优缺点总结


Posted in Java/Android onJuly 15, 2021

什么是Lombok

Lombok是一款Java开发插件,可以通过它定义的注解来精简冗长和繁琐的代码,主要针对简单的Java模型对象(POJO)。

好处就显而易见了,可以节省大量重复工作,特别是当POJO类的属性增减时,需要重复修改的Getter/Setter、构造器方法、equals方法和toString方法等。

而且Lombok针对这些内容的处理是在编译期,而不是通过反射机制,这样的好处是并不会降低系统的性能。

下面我们就看看具体的使用。

Lombok的安装

Lombok的安装分两部分:Idea插件的安装和maven中pom文件的导入。

第一步,在Idea的插件配置中搜索Lombok或官网下载本地安装。

第二步,引入pom中依赖,当前最细版本1.18.10。

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>

不知道什么原因,我在使用Idea安装插件一直失败,所以只在pom中引入了依赖,也是能正常使用。

Lombok的使用

@Data

@Data最常用的注解之一。注解在类上,提供该类所有属性的getter/setter方法,还提供了equals、canEqual、hashCode、toString方法。

这里的提供什么意思?就是开发人员不用手写相应的方法,而Lombok会帮你生成。

使用@Data示例如下,最直观的就是不用写getter/setter方法。

package pojo;

public class User {
    private int id;
    private String name;
    private String pwd;

    public User(int id, String hello, String pwd) {
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}
@Data
public class User {
    private int id;
    private String name;
    private String pwd;

}

对比之下效果显而易见。

@Setter

作用于属性上,为该属性提供setter方法; 作用与类上,为该类所有的属性提供setter方法, 都提供默认构造方法。

public class Demo {
	private int id;
	@Setter
	private String remark;
}
@Setter
public class Demo {
	private int id;
	private String remark;
}

@Getter

基本使用同@Setter方法,不过提供的是getter方法,不再赘述。

@Log4j

作用于类上,为该类提供一个属性名为log的log4j日志对象。

@Log4j
public class Demo {
}

该属性一般使用于Controller、Service等业务处理类上。与此注解相同的还有@Log4j2,顾名思义,针对Log4j2。

@AllArgsConstructor

作用于类上,为该类提供一个包含全部参的构造方法,注意此时默认构造方法不会提供。

@AllArgsConstructor
public class Demo {
	private int id;
	private String remark;
}

效果如下:

public class Demo {
    private int id;
    private String remark;

    public Demo(final int id, final String remark) {
        this.id = id;
        this.remark = remark;
    }
}

@NoArgsConstructor

作用于类上,提供一个无参的构造方法。可以和@AllArgsConstructor同时使用,此时会生成两个构造方法:无参构造方法和全参构造方法。

@EqualsAndHashCode

作用于类上,生成equals、canEqual、hashCode方法。具体效果参看最开始的@Data效果。

@NonNull

作用于属性上,提供关于此参数的非空检查,如果参数为空,则抛出空指针异常。

public class Demo {
	@NonNull
	private int id;
	private String remark;
}

@RequiredArgsConstructor

作用于类上,由类中所有带有@NonNull注解或者带有final修饰的成员变量作为参数生成构造方法。

@Cleanup

作用于变量,保证该变量代表的资源会被自动关闭,默认调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定。

public void jedisExample(String[] args) {
    try {
        @Cleanup Jedis jedis =   redisService.getJedis();
    } catch (Exception ex) {
        logger.error(“Jedis异常:”,ex)
    }
}

效果相当于:

public void jedisExample(String[] args) {

    Jedis jedis= null;
    try {
        jedis = redisService.getJedis();
    } catch (Exception e) {
        logger.error(“Jedis异常:”,ex)
    } finally {
        if (jedis != null) {
            try {
                jedis.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

@ToString

作用于类上,生成包含所有参数的toString方法。见@Data中toString方法。

@Value

作用于类上,会生成全参数的构造方法、getter方法、equals、hashCode、toString方法。与@Data相比多了全参构造方法,少了默认构造方法、setter方法和canEqual方法。

该注解需要注意的是:会将字段添加上final修饰,个人感觉此处有些失控,不太建议使用。

@SneakyThrows

作用于方法上,相当于把方法内的代码添加了一个try-catch处理,捕获异常catch中用Lombok.sneakyThrow(e)抛出异常。使用@SneakyThrows(BizException.class)指定抛出具体异常。

@SneakyThrows
public int getValue(){
	int a = 1;
	int b = 0;
	return a/b;
}

效果如下:

public int getValue() {
    try {
        int a = 1;
        int b = 0;
        return a / b;
    } catch (Throwable var3) {
        throw var3;
    }
}

@Synchronized

作用于类方法或实例方法上,效果与synchronized相同。区别在于锁对象不同,对于类方法和实例方法,synchronized关键字的锁对象分别是类的class对象和this对象,而@Synchronized的锁对象分别是私有静态final对象lock和私有final对象lock。也可以指定锁对象。

public class FooExample { 

 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 FooExample { 

  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 void foo() { 
    synchronized(readLock) { 
        System.out.println("bar");   
    } 
  } 

}

val

使用val作为局部变量声明的类型,而不是实际写入类型。 执行此操作时,将从初始化表达式推断出类型。

public Map<String, String> getMap() {
	val map = new HashMap<String, String>();
	map.put("1", "a");
	return map;
}

效果如下:

public Map<String, String> getMap() {
    HashMap<String, String> map = new HashMap();
    map.put("1", "a");
    return map;
}

也就是说在局部变量中,Lombok帮你推断出具体的类型,但只能用于局部变量中。

@Builder

作用于类上,如果你喜欢使用Builder的流式操作,那么@Builder可能是你喜欢的注解了。

@Builder
public class Demo {
	private int id;
	private String remark;
}

效果如下:

public class Demo {
    private int id;
    private String remark;

    Demo(final int id, final String remark) {
        this.id = id;
        this.remark = remark;
    }

    public static Demo.DemoBuilder builder() {
        return new Demo.DemoBuilder();
    }

    public static class DemoBuilder {
        private int id;
        private String remark;

        DemoBuilder() {
        }

        public Demo.DemoBuilder id(final int id) {
            this.id = id;
            return this;
        }

        public Demo.DemoBuilder remark(final String remark) {
            this.remark = remark;
            return this;
        }

        public Demo build() {
            return new Demo(this.id, this.remark);
        }

        public String toString() {
            return "Demo.DemoBuilder(id="   this.id   ", remark="   this.remark   ")";
        }
    }
}

Lombok的优缺点

优点:

1、能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率
2、让代码变得简洁,不用过多的去关注相应的方法
3、属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等

缺点:

强X队友
因为Lombok的使用要求开发者一定要在IDE中安装对应的插件。如果未安装插件的话,使用IDE打开一个基于Lombok的项目的话会提示找不到方法等错误。导致项目编译失败。也就是说,如果项目组中有一个人使用了Lombok,那么其他人就必须也要安装IDE插件。否则就没办法协同开发。更重要的是,如果我们定义的一个jar包中使用了Lombok,那么就要求所有依赖这个jar包的所有应用都必须安装插件,这种侵入性是很高的。代码可读性,可调试性低
在代码中使用了Lombok,确实可以帮忙减少很多代码,因为Lombok会帮忙自动生成很多代码。
但是这些代码是要在编译阶段才会生成的,所以在开发的过程中,其实很多代码其实是缺失的。
在代码中大量使用Lombok,就导致代码的可读性会低很多,而且也会给代码调试带来一定的问题。
比如,我们想要知道某个类中的某个属性的getter方法都被哪些类引用的话,就没那么简单了。有坑
因为Lombok使代码开发非常简便,这就使得部分开发者对其产生过度依赖。在使用Lombok过程中,如果对于各种注解的底层原理不理解的话,很容易产生意想不到的结果。举一个简单的例子,我们知道,当我们使用@Data定义一个类的时候,会自动帮我们生成equals()方法 。但是如果只使用了@Data,而不使用@EqualsAndHashCode(callSuper=true)的话,会默认@EqualsAndHashCode(callSuper=false),这时候生成的equals()方法只会比较子类的属性,不会考虑从父类继承的属性,无论父类属性访问权限是否开放。这就可能得到意想不到的结果。影响升级
因为Lombok对于代码有很强的侵入性,就可能带来一个比较大的问题,那就是会影响我们对JDK的升级。按照如今JDK的升级频率,每半年都会推出一个新的版本,但是Lombok作为一个第三方工具,并且是由开源团队维护的,那么他的迭代速度是无法保证的。所以,如果我们需要升级到某个新版本的JDK的时候,若其中的特性在Lombok中不支持的话就会受到影响。还有一个可能带来的问题,就是Lombok自身的升级也会受到限制。因为一个应用可能依赖了多个jar包,而每个jar包可能又要依赖不同版本的Lombok,这就导致在应用中需要做版本仲裁,而我们知道,jar包版本仲裁是没那么容易的,而且发生问题的概率也很高。破坏封装性
以上几个问题,我认为都是有办法可以避免的。但是有些人排斥使用Lombok还有一个重要的原因,那就是他会破坏封装性。众所周知,Java的三大特性包括封装性、继承性和多态性。如果我们在代码中直接使用Lombok,那么他会自动帮我们生成getter、setter 等方法,这就意味着,一个类中的所有参数都自动提供了设置和读取方法。

到此这篇关于Lombok的详细使用及优缺点总结的文章就介绍到这了,更多相关Lombok使用内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Java/Android 相关文章推荐
分析Java中Map的遍历性能问题
Jun 26 Java/Android
Spring Boot 实现敏感词及特殊字符过滤处理
Jun 29 Java/Android
Java常用函数式接口总结
Jun 29 Java/Android
Java图书管理系统,课程设计必用(源码+文档)
Jun 30 Java/Android
SpringBoot工程下使用OpenFeign的坑及解决
Jul 02 Java/Android
Java 在生活中的 10 大应用
Nov 02 Java/Android
springboot layui hutool Excel导入的实现
Mar 31 Java/Android
Android超详细讲解组件ScrollView的使用
Mar 31 Java/Android
Java 超详细讲解ThreadLocal类的使用
Apr 07 Java/Android
Java 死锁解决方案
May 11 Java/Android
SpringBoot全局异常处理方案分享
May 25 Java/Android
Java中的Kotlin 内部类原理
Jun 16 Java/Android
Java Socket实现多人聊天系统
看完这篇文章获得一些java if优化技巧
解决Jenkins集成SonarQube遇到的报错问题
java固定大小队列的几种实现方式详解
Jul 15 #Java/Android
gateway网关接口请求的校验方式
spring cloud gateway中如何读取请求参数
Spring Cloud Gateway去掉url前缀
Jul 15 #Java/Android
You might like
php引用返回与取消引用的详解
2013/06/08 PHP
dedecms中使用php语句指南
2014/11/13 PHP
php生成动态验证码gif图片
2015/10/19 PHP
Symfony2学习笔记之模板用法详解
2016/03/17 PHP
PHP设计模式之简单工厂和工厂模式实例分析
2019/03/25 PHP
PHP开发API接口签名生成及验证操作示例
2020/05/27 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
移动节点的jquery代码
2014/01/13 Javascript
在JavaScript中判断整型的N种方法示例介绍
2014/06/18 Javascript
js用typeof方法判断undefined类型
2014/07/15 Javascript
Jquery Post处理后不进入回调的原因及解决方法
2014/07/15 Javascript
jquery实现拖动效果(代码分享)
2017/01/25 Javascript
Vue 组件(component)教程之实现精美的日历方法示例
2018/01/08 Javascript
常见的浏览器存储方式(cookie、localStorage、sessionStorage)
2019/05/07 Javascript
JSON 入门教程基础篇 json入门学习笔记
2020/09/22 Javascript
vue3 watch和watchEffect的使用以及有哪些区别
2021/01/26 Vue.js
[01:34]2014DOTA2展望TI 剑指西雅图VG战队专访
2014/06/30 DOTA
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
python实现问号表达式(?)的方法
2013/11/27 Python
Python实现统计代码行的方法分析
2017/07/12 Python
python学生信息管理系统(完整版)
2020/04/05 Python
python使用插值法画出平滑曲线
2018/12/15 Python
python英语单词测试小程序代码实例
2019/09/09 Python
Python 依赖库太多了该如何管理
2019/11/08 Python
Pyqt助手安装PyQt5帮助文档过程图解
2020/11/20 Python
HTML5实现移动端复制功能
2018/04/19 HTML / CSS
详解HTML5布局和HTML5标签
2020/10/26 HTML / CSS
灵泰克Java笔试题
2016/01/09 面试题
自我鉴定200字
2013/10/28 职场文书
企业项目策划书
2014/01/11 职场文书
高三上学期学习自我评价
2014/04/23 职场文书
经营管理策划方案
2014/05/22 职场文书
区域销售主管岗位职责
2014/06/15 职场文书
保护环境的宣传语
2015/07/13 职场文书
2015年小学教师培训工作总结
2015/07/21 职场文书
关于springboot 配置date字段返回时间戳的问题
2021/07/25 Java/Android