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 相关文章推荐
浅谈Python魔法方法
Jun 28 Java/Android
解决Swagger2返回map复杂结构不能解析的问题
Jul 02 Java/Android
Java后台生成图片的完整步骤
Aug 04 Java/Android
浅谈Java父子类加载顺序
Aug 04 Java/Android
springboot+WebMagic+MyBatis爬虫框架的使用
Aug 07 Java/Android
springboot+zookeeper实现分布式锁
Mar 21 Java/Android
Java Spring Boot 正确读取配置文件中的属性的值
Apr 20 Java/Android
Java Spring Lifecycle的使用
May 06 Java/Android
Java时间工具类Date的常用处理方法
May 25 Java/Android
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
Jun 01 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中die(),exit(),return的区别
2013/06/20 PHP
windows服务器中检测PHP SSL是否开启以及开启SSL的方法
2014/04/25 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
深入浅析PHP的session反序列化漏洞问题
2017/06/15 PHP
PHP实现读取文件夹及批量重命名文件操作示例
2019/04/15 PHP
javascript游戏开发之《三国志曹操传》零部件开发(三)情景对话中仿打字机输出文字
2013/01/23 Javascript
javascript实现焦点滚动图效果 具体方法
2013/06/24 Javascript
js实现div拖动动画运行轨迹效果代码分享
2015/08/27 Javascript
jquery动态导航插件dynamicNav用法实例分析
2015/09/06 Javascript
Bootstrap分页插件之Bootstrap Paginator实例详解
2016/10/15 Javascript
使用json来定义函数,在里面可以定义多个函数的实现方法
2016/10/28 Javascript
JS定时器实现数值从0到10来回变化
2016/12/09 Javascript
详解Angular中的自定义服务Service、Provider以及Factory
2017/04/22 Javascript
React+react-dropzone+node.js实现图片上传的示例代码
2017/08/23 Javascript
使用JavaScript实现node.js中的path.join方法
2018/08/12 Javascript
vue中v-for循环给标签属性赋值的方法
2018/10/18 Javascript
解决VUE mounted 钩子函数执行时 img 未加载导致页面布局的问题
2020/07/27 Javascript
Vue实现多页签组件
2021/01/14 Vue.js
python引用DLL文件的方法
2015/05/11 Python
Python自动调用IE打开某个网站的方法
2015/06/03 Python
详解django中使用定时任务的方法
2018/09/27 Python
Python 把序列转换为元组的函数tuple方法
2019/06/27 Python
Python pip替换为阿里源的方法步骤
2019/07/02 Python
python库skimage给灰度图像染色的方法示例
2020/04/27 Python
python递归函数用法详解
2020/10/26 Python
英国男女豪华配饰和礼品网站:Black.co.uk
2020/02/28 全球购物
物业电工岗位职责
2013/11/20 职场文书
家长学校工作方案
2014/05/07 职场文书
热门专业求职信
2014/05/24 职场文书
酒店管理毕业生自荐信
2014/05/25 职场文书
环保标语口号
2014/06/13 职场文书
国际贸易系求职信
2014/08/09 职场文书
机关干部三严三实心得体会
2014/10/13 职场文书
入党积极分子十八届四中全会思想汇报
2014/10/23 职场文书
干部考察材料范文
2014/12/24 职场文书