一.场景模拟@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()
方法,它的目的是用来创建构建器。