Lombok 介绍
Lombok项目是一个Java库,它会自动插入您的编辑器和构建工具中。
说大白话就是:让我们少敲点代码,从而提高编码效率。
lombok.jar
Maven配置Lombox
org.projectlombok
lombok
1.18.10
IDEA:Lombok插件
说明一下:Lombok插件并不是提供Lombok功能,功能是有jar实现。插件只是便于提示代码等辅助性功能。
具体使用
JavaBeanDemo
public class User {
private Integer userId;
private String username;
private Character sex;
}
生成get/set方法
@Getter/Setter修饰属性,在编译期会生成该属性get/set方法。
@Getter
@Setter
private Integer userId;
@Getter/Setter修饰类,在编译期会生成该类的实例成员get/set方法(不会去生成静态成员的get/set)。
@Getter
@Setter
public class User{
// ...
}
如果我不想生成sex的get方法,怎么办?
@Getter/Setter的注解提供参数AccessLevel value()
AccessLevel是个枚举类,作用是选择生成get/set方法的访问权限,有以下级别:
AccessLevel.PUBLIC (默认)
public Character getSex(){}
AccessLevel.MODULE
Character getSex(){}
AccessLevel.PROTECTED
protected getSex(){}
AccessLevel.PRIVATE
private getSex(){}
AccessLevel.NONE
// 不生成get方法!!!
@Getter
@Setter
public class User{
// ...
// AccessLevel.NONE:不生成getSex()方法
@Getter(AccessLevel.NONE)
private Character sex;
}
编译后的字节码文件 User.class:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.example;
public class User {
private Integer userId;
private String username;
private Character sex;
public User() {
}
public Integer getUserId() {
return this.userId;
}
public String getUsername() {
return this.username;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setSex(Character sex) {
this.sex = sex;
}
}
生成toString方法
@ToString 修饰类,生成该类的toString方法,默认将所有成员变量加入toString方法中。
@ToString
public class User{
// ...
// 编译后将会在class文件中生成toString,如下:
public String toString(){
return "User(userId=" + this.userId + ", username=" + this.username + ", sex=" + this.sex + ")";
}
}
当然,也可以选择性的将成员变量加入toString方法中
@ToString提供字段参数:
String[] exclude() default {} 其作用是将exclude={}中的属性过滤掉不加入toString方法。
举个例子,将sex属性不加入到toString中:
@ToString(exclude = {"sex"})
public class User {
// ...
// 编译后将会在class文件中生成toString,如下:
public String toString() {
return "User(userId=" + this.userId + ", username=" + this.username + ")";
}
}
此外@ToString还提供了参String[] of() default{} 作用是指定成员变量加入toString方法中
只将sex属性加入到toString中
@ToString(of = {"sex"})
public class User{
// ...
// 编译后将会在class文件中生成toString,如下:
public String toString() {
return "User(sex=" + this.sex + ")";
}
}
生成equals和hashCode方法
@EqualsAndHashCode修饰类,会生成3个方法:equals,hashCode和canEquals方法,用于比较该类对象是否相等(默认将所成员变量加入equals和hashCode方法中)。
@EqualsAndHashCode也提供了String[] exclude() default {} 和 String[] of() default{} ,作用分别是将某属性过滤和指定某属性加入equals和hashCode方法中。
@EqualsAndHashCode
public class User{
// ...
// 编译后将会在class文件中生成equals,hashCode,canEquals三个方法,如下:
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$userId = this.userId;
Object other$userId = other.userId;
if (this$userId == null) {
if (other$userId == null) {
break label47;
}
} else if (this$userId.equals(other$userId)) {
break label47;
}
return false;
}
Object this$username = this.username;
Object other$username = other.username;
if (this$username == null) {
if (other$username != null) {
return false;
}
} else if (!this$username.equals(other$username)) {
return false;
}
Object this$sex = this.sex;
Object other$sex = other.sex;
if (this$sex == null) {
if (other$sex != null) {
return false;
}
} else if (!this$sex.equals(other$sex)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $userId = this.userId;
int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
Object $username = this.username;
result = result * 59 + ($username == null ? 43 : $username.hashCode());
Object $sex = this.sex;
result = result * 59 + ($sex == null ? 43 : $sex.hashCode());
return result;
}
}
举个例子,现在只需要比较username是否相等就代表对象相等:
@EqualsAndHashCode(of = {"username"})
public class User{
// ...
// 编译后将会在class文件中生成equals,hashCode,canEquals三个方法,如下:
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 {
Object this$username = this.username;
Object other$username = other.username;
if (this$username == null) {
if (other$username != null) {
return false;
}
} else if (!this$username.equals(other$username)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $username = this.username;
int result = result * 59 + ($username == null ? 43 : $username.hashCode());
return result;
}
}
参数非空验证
@NonNull 作用是判断变量是否为空,若为空则抛出空指针异常。
它可以修饰:
修饰类
修饰成员变量
修饰方法参数
修饰方法返回值
public class User{
// ...
@NonNull
private Character sex;
public void method01(@NonNull Integer val) {
System.out.println(val);
}
@NonNull
public String method02(Integer val) {
return val.toString
}
}
上面代码所生成的class文件
public class User{
// ...
@NonNull
private Character sex;
@NonNull
public Character getSex() {
return this.sex;
}
public void setSex(@NonNull Character sex) {
if (sex == null) {
throw new NullPointerException("sex is marked non-null but is null");
} else {
this.sex = sex;
}
}
public void method01(@NonNull Integer val) {
if (val == null) {
throw new NullPointerException("val is marked non-null but is null");
} else {
System.out.println(val);
}
}
@NonNull
public String method02(Integer val) {
return val.toString();
}
}
生成构造方法
@NoArgsConstructor :修饰类生成无参构造方法
@NoArgsConstructor
public class User{
// ...
// 编译后将会在class文件中生成如下:
public User() {
}
}
@RequiredArgsConstructor : 生成指定属性构造方法
修饰标有final和@NonNull的成员变量声称构造参数(并且这些变量都没有赋值)。
@RequiredArgsConstructor
public class User{
private final Integer userId;
@NonNull private String username;
private Character sex;
// 编译后class文件中生成如下:
public User(Integer userId, @NonNull String username) {
if (username == null) {
throw new NullPointerException("username is marked non-null but is null");
} else {
this.userId = userId;
this.username = username;
}
}
}
@AllArgsConstructor : 生成所有属性构造方法
@AllArgsConstructor
public class User{
private Integer userId;
private String username;
private Character sex;
// 编译后class文件中生成如下:
public User(Integer userId, String username, Character sex) {
this.userId = userId;
this.username = username;
this.sex = sex;
}
}
@Data
@Data修饰类,集成@Getter/Setter + @ToString + @EqualsAndHashCode
@Data
public class User{
// ...
// 编译后class文件中生成如下:
public Integer getUserId(){
return this.userId;
}
public void setUserId(Integer userId){
this.userId = userId;
}
public boolean equals(Object o) {
//...
}
public boolean canEquals(Object o) {
// ...
}
public int hashCode(){
// ...
}
public String toString(){
// ...
}
}
@Builder
@Builder 修饰类,会生成一个内部类: 构造者模式,方便我们链式(流式)编程。
@Data
@Builder
public class User {
//...
// 编译后class文件(User$UserBuilder.class)中生成如下:
public static class UserBuilder {
private Integer userId;
private String username;
private Character sex;
UserBuilder() {
}
public User.UserBuilder userId(Integer userId) {
this.userId = userId;
return this;
}
public User.UserBuilder username(String username) {
this.username = username;
return this;
}
public User.UserBuilder sex(Character sex) {
this.sex = sex;
return this;
}
public User build() {
return new User(this.userId, this.username, this.sex);
}
public String toString() {
return "User.UserBuilder(userId=" + this.userId + ", username=" + this.username + ", sex=" + this.sex + ")";
}
}
}
@Test
public void test(){
User user = User.builder().userId(4).username("王五").sex('M').build();
System.out.println(user);// User(userId=4, username=王五, sex=M)
}
@Log
@Log修饰类,会生成一个日志对象。
@Log
public class User{
// ...
// 编译后class文件(User$UserBuilder.class)中生成一个log对象
private static final Logger log = Logger.getLogger(User.class.getName());
// 自己写的方法
public void logInfo(){
log.info("2020-05-24 21:47:05");
}
}
关键字:val
val 是一个关键,用于修饰变量,可以泛指所有类型,实际上在编译期确定类型。
@Test
public void test(){
val num = 123;
val str = "张三";
valmap = new HashMap();
System.out.println(num); // ok
System.out.println(str); // ok
System.out.println(map); // ok
// ----------- JDK 10 增加关键字 var (注意区分!!!)
var n = 321;
var s = "李四";
var user = new User();
System.out.println(n); // ok
System.out.println(s); // ok
System.out.println(user); // ok
}
@Cleanup
@Cleanup 修饰属性,自动释放该属性资源。
@Test
public void test() throws IOException {
@Cleanup InputStream is = System.in;
int len = 0;
byte[] buf = new byte[1024];
while((is.read(buf)) != -1) {
// ...
}
}
编译后class文件
@Test
public void test() throws IOException {
InputStream is = System.in;
try {
int len = false;
byte[] buf = new byte[1024];
while(true) {
if (is.read(buf) != -1) {
continue;
}
}
} finally {
if (Collections.singletonList(is).get(0) != null) {
is.close();
}
}
}
@SneakyThrows
@SneakyThrows 修饰方法,代表该方法的throws.....
@SneakyThrows
public void threadSleep01(int millis) {
Thread.sleep(millis);
}
@SneakyThrows(InterruptedException.class)
public void threadSleep(int millis) {
Thread.sleep(millis);
}
// 编译后字节码文件
public void threadSleep01(long millis) {
try {
Thread.sleep((long)millis);
} catch (Throwable var3) {
throw var3;
}
}
public void threadSleep02(int millis) {
try {
Thread.sleep((long)millis);
} catch (InterruptedException var3) {
throw var3;
}
}
@Value
@Value修饰类,和@Data大概一致,集成@Getter/Setter + @ToString + @EqualsAndHashCode ,代码片段参考@Data。
@Synchronized
@Synchronized修饰方法(静态方法成员方法),给修饰的方法上锁
@Synchronized
public void instanceMethod(){
// ...
}
@Synchronized
public static void staticMethod(){
// ...
}
// 编译后class文件
private final Object $lock = new Object[0];
private static final Object $LOCK = new Object[0];
public void instanceMethod() {
synchronized(this.$lock) {
;
}
}
public static void staticMethod() {
synchronized($LOCK) {
;
}
}
以上是Lombok基本入门,有待深入。