Lombok可以简化常见代码。
第一个例子,@Getter
和 @Setter
通常我们这么写代码:
package net.ffish.lombok.demo;
public class TestEntity {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
利用lombok可以简化为
package net.ffish.lombok.demo;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TestEntity {
private int age;
private String name;
}
@Getter 和 @Setter 也可以用在变量上:
package net.ffish.lombok.demo;
import lombok.Getter;
import lombok.Setter;
public class TestEntity {
@Getter
private int age;
@Setter
private String name;
@Getter
@Setter
private String nickname;
}
如何引用 lombok
maven:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
</dependencies>
gradle:
repositories {
mavenCentral()
}
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
testCompileOnly 'org.projectlombok:lombok:1.18.20'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.20'
}
@ToString
package net.ffish.lombok.demo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ToString
public class TestEntity {
private int age;
private String name;
@ToString.Exclude // 可以通过这个注解来排除被标记的变量
private String nickname;
}
@NonNull
@NonNull
会生成检查代码:
package net.ffish.lombok.demo;
import lombok.*;
@ToString
public class TestEntity {
private int age;
private String name;
private String nickname;
public TestEntity(@NonNull Integer age) {
this.age = age;
}
}
如果像下面这样调用,则会抛出java.lang.NullPointerException
TestEntity testEntity = new TestEntity(null);
@NoArgsConstructor、@AllArgsConstructor 和 @RequiredArgsConstructor
@NoArgConstructor
会自动生成无参构造函数。@AllArgsConstructor
会自动生成包含所有成员变量的构造函数,如果某个成员变量被标记为@NonNull
,则为其生成null
检查的代码。@RequiredArgConstructor
生成的构造函数会为未初始化的final
型成员变量和@NonNull
型的成员变量生成对应参数,并为@NonNull
型变量生成null
检查代码。
@EqualsAndHashCode
关于equals()
和hashCode()
的经典问题,参考阿里巴巴编码规范:
- 只要覆写
equals
,就必须覆写hashCode
。- 因为
Set
存储的是不重复的对象,依据hashCode
和equals
进行判断,所以Set
存储的对象必须覆写这两种方法。- 如果自定义对象作为
Map
的键,那么必须覆写hashCode
和equals
。
说明:String
因为覆写了hashCode
和equals
方法,所以可以愉快地将String
对象作为key
来使用。
@EqualsAndHashCode
注解会为我们生成equals()
和hashCode()
函数。
- 默认情况下会选用非
static
和非transient
字段来构造这两个函数。 - 通过
@EqualsAndHashCode.Exclude
来排除某个字段。 - 通过
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
和@EqualsAndHashCode.Include
的设置来精确指定某些字段。
package net.ffish.lombok.demo;
import lombok.*;
@EqualsAndHashCode
public class TestEntity {
@EqualsAndHashCode.Exclude
private int age;
private String name;
private String nickname;
}
大集合 @Data
@Data
是几个常用 lombok 注解的集合,只需要写@Data
一个注解,就可代替以下几个注解:
- @ToString
- @EqualsAndHashCode
- @Getter 所有成员变量
- @Setter 非
final
型成员变量 - @RequiredArgsConstructor
Using @Data for JPA entities is not recommended. It can cause severe performance and memory consumption issues.
对于 JPA 的Entity
,不推荐使用@Data
,因为它会造成一些性能和内存消耗的问题,建议逐一写上这几个注解。
@Value
@Value
是@Data
的另一种形式,有以下几点不同:
- 类被设置为
final
- 所有缺省成员变量都被设置为
final
和private
,因此也不会生成setter()
方法
因此,@Value
等同于
final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter
@Cleanup
自动调用close()
方法,如下:
package net.ffish.lombok.demo;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
@Cleanup InputStream in = new FileInputStream(args[0]);
@Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
等同于
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
if (out != null) {
out.close();
}
}
} finally {
if (in != null) {
in.close();
}
}
}
}
如果目标对象没有close()
方法,而是其他无参的关闭函数,例如dispose()
,可以这样做:
@Cleanup("dispose") TestObject = new TestObject();
其他注解
个人不推荐使用lombok的其他注解。
前面提到的那些注解代替我们生成一些简单、重复但必要的代码,简化代码,节省时间。
但lombok的其他的注解则会改变我们的编码习惯,侵入性过强,可读性不高,使得代码与lombok深度绑定,使得java不像java,因此不推荐使用。他们是:
- val 局部变量自动推断类型,并声明为
final
类型
val example = new ArrayList<String>();
// 等同于 final ArrayList<String> example = new ArrayList<String>();
- var 用法等同于
val
,但变量不会被声明为final
类型。 - @Builder 帮助我们自动创建
builder()
代码。 - @SneakyThrows 代替你无脑抛异常
- @Synchronized 代替声明锁变量并加锁
- @With 克隆对象,并允许修改一个成员变量
- @Getter(lazy=true) 懒汉式
getter()
- @Log 用于代替声明不同类型的
logger
变量
感兴趣的可以去官网查看。https://projectlombok.org
飞鱼原创 https://ffish.net,未经允许,严禁转载!