今天为大家推荐一个java的开发神器lombok,可以帮助大家节省开发时间,提升工(mo)作(yu)效(shi)率(jian)。
一、基本介绍
Lombok是一款Java开发插件,可以通过它定义的注解来精简冗长和繁琐的代码,主要针对简单的Java模型对象(POJO)。
好处就显而易见了,可以节省大量重复工作,特别是当POJO类的属性增减时,需要重复修改的Getter/Setter、构造器方法、equals方法和toString方法等。
而且Lombok针对这些内容的处理是在编译期,而不是通过反射机制,这样的好处是并不会降低系统的性能。
目前Lombok已经支持JDK14和JDK13的一些特性
二、IDE安装Lombok开发工具
Lombok的官网中详细的介绍了各种IDE安装Lombok的方法,目前已经指出IDEA、Eclipse、Netbeans、Myeclipse、Spring boot Suite、Visual Studio Code等工具,本文以IDEA为例,介绍安装的方法,其他IDE的安装方法按照官网的方式进行安装。
2.1 在线安装
点击File -> Settings -> Plugins
-
在marketplace中搜索Lombok
-
点击install
-
Restart IntelliJ IDEA
2.2 离线安装
在一些管理比较严格的公司里,开发环境不允许连接外网,离线安装的方法主要方便这些苦难的兄弟
1.进入jetbrains官网,找到Lombook插件
2.根据自己IDEA版本选择对应的版本
-
点击File -> Settings -> Plugins,选择install plugins from disk
4.选择下载的插件,后续与在线安装过程一致
注意:选择下载插件时,一定要与IDEA的版本一致,如不一致,会提示不可用,或者安装失败
三、引入依赖
Lombok的官网中分别介绍了maven、gradle、ant和Kobalt四种构建工具如何引入Lombok,本文以maven为例进行简单的介绍,其他构建工具可以参考官网的文档
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
其中,1.18.12版本为当前最新版本,<scope>provided</scope> 表示编译时不会将其打包war/jar包中。
四、注解简介
Lombok的所有注解可以通过官网Lombok features查看
1. @Getter/@Setter
这两个注意应该是使用lombok中最常用的的两个注解,一个属性foo,通过@Getter
注解生成的get方法的方法名为getFoo(),如果该属性为boolean,则方法名为isFoo();set方法名为setFoo,返回值为void。
@Setter
/@Getter
生成的方法为public,如果想要修改方法的访问修饰符,可以使用AccessLevel进行限制,AccessLevel支持所有的访问修饰符(PUBLIC、PROTECTED、PACKAGE、PRIVATE)
@Setter(AccessLevel.PROTECTED) private String name;
官网示例:
Lombok版本
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
public class GetterSetterExample {
/**
* Age of the person. Water is wet.
*
* @param age New value for this person's age. Sky is blue.
* @return The current value of this person's age. Circles are round.
*/
@Getter @Setter private int age = 10;
/**
* Name of the person.
* -- SETTER --
* Changes the name of this person.
*
* @param name The new value.
*/
@Setter(AccessLevel.PROTECTED) private String name;
@Override public String toString() {
return String.format("%s (age: %d)", name, age);
}
}
不使用Lombok的程序
public class GetterSetterExample {
/**
* Age of the person. Water is wet.
*/
private int age = 10;
/**
* Name of the person.
*/
private String name;
@Override public String toString() {
return String.format("%s (age: %d)", name, age);
}
/**
* Age of the person. Water is wet.
*
* @return The current value of this person's age. Circles are round.
*/
public int getAge() {
return age;
}
/**
* Age of the person. Water is wet.
*
* @param age New value for this person's age. Sky is blue.
*/
public void setAge(int age) {
this.age = age;
}
/**
* Changes the name of this person.
*
* @param name The new value.
*/
protected void setName(String name) {
this.name = name;
}
}
示例中的@Setter
和@Getter
注解分别放到了具体的属性前,在开发过程中,通常直接放到类的定义前,这样表示该类中的所有属性都要生成set/get方法
2.@NonNull
作用于属性上,提供关于此参数的非空检查,如果参数为空,则抛出空指针异常。
非空检查的代码示例如下:
if (param == null)
throw new NullPointerException("param is marked @NonNull but is null")
官方示例:
Lombok版本
public class NonNullExample extends Something {
private String name;
public NonNullExample(@NonNull Person person) {
super("Hello");
this.name = person.getName();
}
}
不带Lombok版本
public class NonNullExample extends Something {
private String name;
public NonNullExample(Person person) {
super("Hello");
if (person == null) {
throw new NullPointerException("person is marked @NonNull but is null");
}
this.name = person.getName();
}
}
注意:官网中Vanilla Java版本中在Person person前增加了@NonNull
注解,应该是编写错误,此处特意进行说明
3.@NoArgsConstructor/@RequiredArgsConstructor/@AllArgsConstructor
这三个注解主要是生成构造函数的标签,其中:
@NoArgsConstructor
表示生成一个不带参数的构造方法;
@RequiredArgsConstructor
表示生成一些特定属性的构造方法,特定参数包括final的字段和标记@NonNull
的字段;使用该标签生成的构造方法的访问修饰符为private,可以增加staticName属性值,该属性默认为“”,增加该属性后,会默认生成一个名为staticName值的构造方法,其访问修饰符为public的静态方法,参数与@RequiredArgsConstructor
参数一致
@AllArgsConstructor
表示生成所有属性的构造方法;
官方示例:
Lombok版本
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.AllArgsConstructor;
import lombok.NonNull;
@RequiredArgsConstructor(staticName = "of")
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@NoArgsConstructor
public class ConstructorExample<T> {
private int x, y;
@NonNull private T description;
}
不带Lombok版本
public class ConstructorExample<T> {
private int x, y;
@NonNull private T description;
}
// @NoArgsConstructor对应的构造方法
private ConstructorExample(T description) {
}
// @RequiredArgsConstructor对应的构造方法
private ConstructorExample(T description) {
if (description == null) throw new NullPointerException("description");
this.description = description;
}
// 增加staticName后生成的构造方法
public static <T> ConstructorExample<T> of(T description) {
return new ConstructorExample<T>(description);
}
// @AllArgsConstructor对应的构造方法
@java.beans.ConstructorProperties({"x", "y", "description"})
protected ConstructorExample(int x, int y, T description) {
if (description == null) throw new NullPointerException("description");
this.x = x;
this.y = y;
this.description = description;
}
官方给出的示例让人看起来有点摸不着头脑,为了方便清楚的明白这三个标签,将官方的示例进行调整,效果可能会更好一点。
查看使用三个注解生成的方法,与不使用Lombok的构造方法完全一致
4. @ToString
@ToString
自动生成一个toString()方法,默认情况是所有的字段都在进行字符串输出,当然,可以使用@ToString.Exclude
的方式排除一些字段不显示输出。
5.@Data
@Data注解集成了@ToString
、@EqualsAndHashCode
、@Getter
/ @Setter
和@RequiredArgsConstructor
6.@EqualsAndHashCode
@EqualsAndHashCode
生成hashCode()
、canEqual
和equals()
方法
7.val/var
使用val
作为局部变量声明的类型,而不是实际写入类型。 执行此操作时,将从初始化表达式推断出类型。
var
与val
几乎一样,只是变量前没有final的定义
我理解var和val与javascript中的左右几乎相同,在对变量赋值之后在进行赋值,这两个属性不是注解,是一个类,实际场景中可能的用途不是太多
官方示例:
Lombok版本
import java.util.ArrayList;
import java.util.HashMap;
import lombok.val;
public class ValExample {
public String example() {
val example = new ArrayList<String>();
example.add("Hello, World!");
val foo = example.get(0);
return foo.toLowerCase();
}
}
不带Lombok版本
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class ValExample {
public String example() {
final ArrayList<String> example = new ArrayList<String>();
example.add("Hello, World!");
final String foo = example.get(0);
return foo.toLowerCase();
}
}
其他的属性可以参考官网中稳定版本的特性列表,不在额外叙述
五、关于Lombok的一些争议
之前在网上有人发布Lombok是让你代码处于“亚健康”状态的真正元凶,提出Lombok存在的四个问题:
* JDK8升级到JDK11后,Lombok不能使用
* 胁迫使用:当你的源代码中使用了Lombok,恰好你的代码又被其他的人所使用,那么依赖你代码的人,也必须安装Lombok插件
* 可读性差:Lombok隐藏了JavaBean封装的细节,所有JavaBean中的方法你只能想象他们长什么样子,你并不能看见
* 代码耦合度增加:当你使用Lombok来编写某一个模块的代码后,其余依赖此模块的其他代码都需要引入Lombok依赖,同时还需要在IDE中安装Lombok的插件,这是一种入侵式的耦合
关于第一个问题,其实是Lombok的版本原因,在项目中使用了相对较低的版本,会存在升级JDK后不能使用的问题,升级到最新的Lombok就可,那会不会有有问题呢?呵呵呵,JDK都升级了还怕插件升级有问题吗?
关于第二点,的确是不可避免的事实,既然都是使用到代码级别,那应该是一个团队或者一个公司级别,换一个思路思考,那团队或者公司要求使用相同的架构和框架是不是也很合理?
关于第三个问题,实际上可以适当的选择Lombok的注解,对于不好用的注解可以选择不使用。在我看来,@Getter
和@Setter
就可以解决我大量的工作
关于第四个问题,实际上可以使用maven的配置就可以解决相关问题,可以增加<optional>true</optional>
,这样依赖可以不传给引用的项目。
参考文献
1.Project Lombok
2.Java开发神器Lombok使用详解
3.Lombok是让你代码处于“亚健康”状态的真正元凶