生产力工具 ~ Lombok。
文章目录
Lombok ~ what。
https://projectlombok.org/
Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.
Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
消除工作中大量重复的、毫无技术含量的 get(); 、 set(); 方法。
原理。
JSR 269 插件化注解处理 API ~ Pluggable Annotation Processing API。
https://jcp.org/en/jsr/detail?id=269
jdk 6 提供的特性。在 javac 编译期利用注解搞事情。
@Retention(RetentionPolicy.SOURCE)
安装。
使用。
- 拷贝 lombok.jar 到类路径。
- javac -cp lombok.jar …
pom 依赖。
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
IDEA 中使用。
IntelliJ IDEA
The Jetbrains IntelliJ IDEA editor is compatible with lombok.
~
Add the Lombok IntelliJ plugin to add lombok support for IntelliJ:
~
Go to File > Settings > Plugins
Click on Browse repositories…
Search for Lombok Plugin
Click on Install plugin
Restart IntelliJ IDEA
You can also check out Setting up Lombok with Eclipse and IntelliJ, a blog article on baeldung.
- 使用了 @Data 注解。前后对比。
注:安装插件是为了 IDEA 的友好提示。如果不安装插件,IDEA 智能提示代码会报红,但仍可以编译运行。
常用注解。
用在类声明上 ~ @Data。
也可以在类成员上单独使用。
package com.geek.lombok;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
//@Data
public class User {
@Getter(AccessLevel.PROTECTED)
@Setter
private Integer id;
private String userName;
private String password;
private String phone;
private String email;
}
查看 .class 文件。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.geek.lombok;
public class User {
private Integer id;
private String userName;
private String password;
private String phone;
private String email;
public User() {
}
protected Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
}
还可以在类声明上使用 @Getter 和 @Setter。
类声明上使用了 @Data,单个成员变量排除使用 ~ @Getter(AccessLevel.NONE)。
@Getter(AccessLevel.NONE)
private String phone;
注意。
- static 的成员变量不会有 setter and getter。
- final 类型只生成 get();。
@ToString
- Java 中,如果不重写 toString(); 方法,则使用继承自 Object 类的 toString(); 方法。此时如果
System.out.println(user);
,控制台会打印出这个对象的内存地址值。
com.geek.lombok.User@74a14482
- 重写了 toString(); 方法,
System.out.println(user);
就会打印出这个对象的属性值。
public String toString() {
return "User(id=" + this.getId() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ", phone=" + this.getPhone() + ", email=" + this.getEmail() + ")";
User(id=1, username=Geek, password=null, phone=null, email=liyifan@lyfGeek.club)
@ToString(exclode = {“”, “”}) 参数可以指定排除的字段。
@ToString(exclude = {“phone”})
@ToString(of = {“”, “”}) 参数可以指定输出字段。
@EqualsAndHashCode。
会生成 equals(); canEqual(); 和 hashCode() 三个方法。
用于判定两个对象是否相等,可以通过重写 equals(); 方法修改判定标准。(eg. 只要 id 和 username 两者相等,我们就认为这两个对象相同)。如果不重写,就必须两个对象的属性全部相同,并且地址值也相同。
~
eg. 使用 @EqualsAndHashCode(exclude = “password”) ——> 如果 id 和 name 相同,我们就认为这两个对象相同。
canEqual();
protected boolean canEqual(Object other) {
return other instanceof User;
}
// 判断对象是不是某个类的实例。
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$id = this.getId();
Object other$id = other.getId();
if (this$id == null) {
if (other$id == null) {
break label47;
}
} else if (this$id.equals(other$id)) {
break label47;
}
return false;
}
Object this$username = this.getUsername();
Object other$username = other.getUsername();
if (this$username == null) {
if (other$username != null) {
return false;
}
} else if (!this$username.equals(other$username)) {
return false;
}
Object this$password = this.getPassword();
Object other$password = other.getPassword();
if (this$password == null) {
if (other$password != null) {
return false;
}
} else if (!this$password.equals(other$password)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.getId();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $username = this.getUsername();
result = result * 59 + ($username == null ? 43 : $username.hashCode());
Object $password = this.getPassword();
result = result * 59 + ($password == null ? 43 : $password.hashCode());
return result;
}
@NonNull。
public void test(@NonNull String s) {
System.out.println(s);
}
如果传入 null 参数。会报异常。
user.test(null);
Exception in thread “main” java.lang.NullPointerException: s is marked non-null but is null
看看编译后的代码。
public void test(@NonNull String s) {
if (s == null) {
throw new NullPointerException("s is marked non-null but is null");
} else {
System.out.println(s);
}
}
Constructor。
@NoArgsConstructor
@RequiredArgsConstructor
@RequiredArgsConstructor
会默认为final
类型的成员变量(并且没有赋初始值)和@NonNull
注解的成员变量生成构造方法。
@Getter
@Setter
@RequiredArgsConstructor
public class User {
// @Getter(AccessLevel.PROTECTED)
// @Setter
final int id2;
@NonNull
private Integer id;
private String username;
private String password;
}
public User(int id2, @NonNull Integer id) {
if (id == null) {
throw new NullPointerException("id is marked non-null but is null");
} else {
this.id2 = id2;
this.id = id;
}
}
@AllArgsConstructor
@Data = @Getter / @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor。
@Builder
函数式编程。
package com.geek.lombok;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
@Data
@Builder
public class User {
final int id2;
@NonNull
private Integer id;
private String username;
private String password;
public static void main(String[] args) {
User user = User.builder().id(1).username("geek").password("123").build();
System.out.println("user = " + user);
}
@Log。
package com.geek.lombok;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.java.Log;
@Data
@Builder
@Log
public class User {
final int id2;
@NonNull
private Integer id;
private String username;
private String password;
public static void main(String[] args) {
User user = User.builder().id(1).username("geek").password("123").build();
System.out.println("user = " + user);
user.test("test_hello");
}
public void test(@NonNull String s) {
System.out.println(s);
log.info("log_info");
}
}
~
user = User(id2=0, id=1, username=geek, password=123)
test_hello
Mar 28, 2020 12:19:48 AM com.geek.lombok.User test
INFO: log_info
val。
import lombok.val;
// 编译时再指定类型。
val map = new HashMap<>();
@Cleanup。
@Cleanup InputStream inputStream = new FileInputStream("~/test.txt");
@Cleanup OutputStream outputStream = new FileOutputStream("path");
// 就不需要 .close(); 了。