@Builder用法
一.场景模拟@Data两个缺点
假如有一结果api结果返回值的类Result,其在代码中频繁被使用:
@Data
public class Result<T> {
private int code;
private String message;
private T data;
public Result(int code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
}
如果要使用它,一般的方法是:
public class Main {
public static void main(String[] args) {
//方法1,使用全量的构造函数
User result1 = new User( "你", "好");
//方法2,使用空的构造函数加setter函数赋值
User user = new User();
user.setUsername("你");
user.setPassword("好");
}
}
这两种使用方法的弊端有:
(1)方法一:当只需要部分参数的时候需要再定义个构造函数(比如只要username,不要password),且一旦参数较多,则构造函数冗长;
(2)方法二:setter冗长;
因此我们需要builder
来解决这个问题
二.java实现@builder
@Builder
public class User {
private final Integer code = 200;
private String username;
private String password;
}
// 编译后:
public class User {
private String username;
private String password;
User(String username, String password) {
this.username = username; this.password = password;
}
public static User.UserBuilder builder() {
return new User.UserBuilder();
}
public static class UserBuilder {
private String username;
private String password;
UserBuilder() {}
public User.UserBuilder username(String username) {
this.username = username;
return this;
}
public User.UserBuilder password(String password) {
this.password = password;
return this;
}
public User build() {
return new User(this.username, this.password);
}
public String toString() {
return "User.UserBuilder(username=" + this.username + ", password=" + this.password + ")";
}
}
}
public static void main(String[] args) {
User user = User.builder()
.username("ni")
.password("44")
.build();
System.out.println(user);
//User(code=200, username=ni, password=44)
}
三.@builder在内部帮我们做了什么
- 创建一个名为
ThisClassBuilder
的内部静态类,并具有和实体类形同的属性(称为构建器)。 - 在构建器中:对于目标类中的所有的属性和未初始化的
final
字段,都会在构建器中创建对应属性。 - 在构建器中:创建一个无参的
default
构造函数。 - 在构建器中:对于实体类中的每个参数,都会对应创建类似于
setter
的方法,只不过方法名与该参数名相同。 并且返回值是构建器本身(便于链式调用),如上例所示。 - 在构建器中:一个
build()
方法,调用此方法,就会根据设置的值进行创建实体对象。 - 在构建器中:同时也会生成一个
toString()
方法。 - 在实体类中:会创建一个
builder()
方法,它的目的是用来创建构建器。