lombok使用

发布时间 2023-07-15 19:14:01作者: theSummerDay

参考

https://projectlombok.org/features/

添加依赖

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

@Getter和@Setter

自动生成Getter和Setter方法

import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;

public class User {
	@Getter @Setter	private Integer id;
	@Setter(AccessLevel.PROTECTED) private String name;
}

等效的java代码

public class User {
	private Integer id;
	private String name;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	protected void setName(String name) {
		this.name = name;
	}
}

@ToString

自动生成toString()方法

import lombok.ToString;

@ToString
public class User {
	private Integer id = 1;
	private String name = "zhangsan";
	private String password = "xxx";

	public static void main(String[] args) {
		User user = new User();
		System.out.println(user);
	}
}

执行结果

User(id=1, name=zhangsan, password=xxx)

等效的toString()代码

	@Override
	public String toString() {
		return "User{" + "id=" + id + ", name=" + name + ", password=" + password + "}";
	}

idea自动生成的toString()会将String类型用单引号'括起来, 二者略有差别

    @Override
	public String toString() {
		return "User{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + '}';
	}

对应结果为:

User{id=1, name='zhangsan', password='xxx'}

如果只想展示部分字段, 可用of来指定字段, 或者使用exclude来排除字段

@ToString(of = {"id", "name"})

或者
@ToString(exclude = {"password"})

或者直接注解字段 @ToString.Exclude
@ToString.Exclude private String password = "xxx";

对应结果为:

User(id=1, name=zhangsan)

@EqualsAndHashCode

除了生成equals()hashCode(), 还有一个canEqual(Object other), 用来判断对象other是否是当前类的实例
官网示例: https://projectlombok.org/features/EqualsAndHashCode

构造方法

@NoArgsConstructor: 无参构造方法

@AllArgsConstructor: 全参构造方法

@RequiredArgsConstructor: 部分参数构造方法,需要搭配@NonNull使用

官网示例: https://projectlombok.org/features/constructor

@Data

一般情况下, 这一个注解就相当于上面的 @Getter @Setter @ToString @EqualsAndHashCode @NoArgsConstructor

Alt text

如果有字段加了@NonNull, 则相当于 @RequiredArgsConstructor

Alt text

也可以通过以下命令来验证:

#编译.java文件,生成.class文件
javac -cp .\lombok-1.18.16.jar .\User.java
#反编译.class文件,查看类的具体信息
javap User

Alt text

@Cleanup

资源操作时,自动调用close()方法

import lombok.Cleanup;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TestCleanup {

	public static void main(String[] args) throws IOException {
		@Cleanup InputStream is = new FileInputStream("/home/1.txt");
		@Cleanup OutputStream os = new FileOutputStream("/home/2.txt");
		byte[] bytes = new byte[1024];
		while (true) {
			int length = is.read(bytes);
			if (length == -1) {
				break;
			}
			os.write(bytes, 0, length);
		}
	}
}

等效的java代码

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TestCleanup {

	public static void main(String[] args) throws IOException {
		InputStream is = new FileInputStream("/home/1.txt");
		try {
			OutputStream os = new FileOutputStream("/home/2.txt");
			try {
				byte[] bytes = new byte[1024];
				while (true) {
					int length = is.read(bytes);
					if (length == -1) {
						break;
					}
					os.write(bytes, 0, length);
				}
			} finally {
				if (os != null) {
					os.close();
				}
			}
		} finally {
			if (is != null) {
				is.close();
			}
		}
	}
}

@Builder

import lombok.Builder;

@Builder
public class User {
	private Integer id;
	private String name;
}

可以实现链式调用的写法,赋值方便

User user = User.builder().id(1).name("zhangsan").build();

反编译后

public class User {
    private Integer id;
    private String name;

    User(Integer var1, String var2) {
        this.id = var1;
        this.name = var2;
    }

    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    public static class UserBuilder {
        private Integer id;
        private String name;

        UserBuilder() {
        }

        public User.UserBuilder id(Integer var1) {
            this.id = var1;
            return this;
        }

        public User.UserBuilder name(String var1) {
            this.name = var1;
            return this;
        }

        public User build() {
            return new User(this.id, this.name);
        }

        public String toString() {
            return "User.UserBuilder(id=" + this.id + ", name=" + this.name + ")";
        }
    }
}

编译后的代码中, 多了一个静态内部类 User.UserBuilder, 属性和 User 相同

  1. 每个属性都有一个类似 setter 的方法, 但返回的是对象本身, 使得可以实现链式调用的写法
  2. @Builder 会默认生成一个全参构造方法, 如果想用无参构造方法需要把 @NoArgsConstructor@AllArgsConstructor 都加上
  3. 如果只加了 @NoArgsConstructor 会覆盖全参构造方法,导致报错
    Alt text

优点: 链式调用写法赋值更方便, 注意如果赋值较多,不要写在一行,不利于阅读维护
缺点: 生成User示例之前, 会先生成User.UserBuilder实例,额外占用内存

选项toBuilder, 默认false, 为true时, 会多一个toBuilder()方法

@Builder(toBuilder = true)
public class User {
    //...
}

//编译后代码
public class User {
    //...
    //编译后多了一个 toBuilder()方法
    //用当前对象的属性来构造一个新的Builder对象
    public User.UserBuilder toBuilder() {
        return (new User.UserBuilder()).id(this.id).name(this.name);
    }
    //...
}