有没有办法在IntelliJ中自动编写Builder模式?
例如,给定这个简单的类:
class Film {
private String title;
private int length;
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return this.title;
}
public void setLength(int length) {
this.length = length;
}
public int getLength() {
return this.length;
}
}
有没有办法可以让IDE生成这个或类似的东西:
public class FilmBuilder {
Film film;
public FilmBuilder() {
film = new Film();
}
public FilmBuilder withTitle(String title) {
film.setTitle(title);
return this;
}
public FilmBuilder withLength(int length) {
film.setLength(length);
return this;
}
public Film build() {
return film;
}
}
答案 0 :(得分:92)
使用Replace Constructor with Builder重构。
要使用此功能,请在代码中单击构造函数的签名,然后右键单击并选择“Refactor”菜单,然后单击“使用Builder替换构造函数...”以打开对话框以生成代码。
答案 1 :(得分:20)
我发现IntelliJ中的内置构建器模式生成有点笨重,原因如下:
command+N
)快速访问。InnerBuilder plugin解决了所有这些缺点,无需设置或配置。这是插件生成的示例生成器:
public class Person {
private String firstName;
private String lastName;
private int age;
private Person(Builder builder) {
firstName = builder.firstName;
lastName = builder.lastName;
age = builder.age;
}
public static final class Builder {
private String firstName;
private String lastName;
private int age;
public Builder() {
}
public Builder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder lastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(this);
}
}
}
答案 2 :(得分:13)
以下是如何克服 Mansoor Siddiqui提到的shortcomings :
1)它需要使用现有的构造函数作为参考。
这很容易生成。只需在Windows上按 Alt + Ins 调用生成菜单,然后选择Constructor
。
2)通过" Generate"无法快速访问。 menu(OS X上的命令+ N)
只需转到Settings -> Keymap
,搜索Builder
并为其指定一个快捷方式(如果您经常使用此功能,这种情况很少见)。例如,您可以指定 Alt + B 。
另一种选择是 Ctrl + Shift + A (查找动作)。开始输入Builder
,您就可以立即访问命令:
您可以使用此快捷方式快速访问任何IntelliJ IDEA功能(当您不记得该命令的确切内容以及在何处找到它时,这会有很大帮助。)
3)它只生成外部Builder类。正如其他人所提到的,在实现构建器模式时使用静态内部类非常常见。
我也更喜欢我的构建器作为静态内部类。不幸的是,没有直接的方法来做到这一点,但它仍然可行。您只需自己定义嵌套的内部类(保持为空),并在调用Replace Constructor with Builder
对话框时,选择Use existing
选项并选择内部类。奇迹般有效!虽然,将此选项配置起来会更容易。
答案 3 :(得分:9)
如果您想知道这是否可用于创建内部构建器类为described by Joshua Block的类 - 您只需先定义一个空内部类,然后选中"使用现有"并搜索你新创建的(内部类)并点击" Refactor"。
PS!游标必须驻留在构造函数内(预先编写),以便使用"将构造函数替换为Builder"重构功能。
答案 4 :(得分:5)
IntelliJ的方法是恕我直言,这是令人费解的。有两个插件(我更喜欢这个插件:https://plugins.jetbrains.com/plugin/7354)更好地服务于目的。
例如,我更喜欢将Builder类作为PoJo的内部类。要使用IntelliJ实现这一点,您需要额外的笔画。
该插件的另一个好处是功能的位置(在Generate...
上下文菜单中)。
答案 5 :(得分:1)
龙目岛是做到这一点的最佳方法! (它具有用于语法支持https://plugins.jetbrains.com/plugin/6317-lombok-plugin的Intellij插件)
只需添加一个@Builder
批注,然后在墙后将在对象内添加一个构建器实现。如今,龙目岛就像一个行业标准:)
与龙目岛:
import lombok.Builder;
import lombok.Singular;
import java.util.Set;
@Builder
public class BuilderExample {
@Builder.Default private long created = System.currentTimeMillis();
private String name;
private int age;
@Singular private Set<String> occupations;
}
没有龙目岛:
import java.util.Set;
public class BuilderExample {
private long created;
private String name;
private int age;
private Set<String> occupations;
BuilderExample(String name, int age, Set<String> occupations) {
this.name = name;
this.age = age;
this.occupations = occupations;
}
private static long $default$created() {
return System.currentTimeMillis();
}
public static BuilderExampleBuilder builder() {
return new BuilderExampleBuilder();
}
public static class BuilderExampleBuilder {
private long created;
private boolean created$set;
private String name;
private int age;
private java.util.ArrayList<String> occupations;
BuilderExampleBuilder() {
}
public BuilderExampleBuilder created(long created) {
this.created = created;
this.created$set = true;
return this;
}
public BuilderExampleBuilder name(String name) {
this.name = name;
return this;
}
public BuilderExampleBuilder age(int age) {
this.age = age;
return this;
}
public BuilderExampleBuilder occupation(String occupation) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.add(occupation);
return this;
}
public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
if (this.occupations == null) {
this.occupations = new java.util.ArrayList<String>();
}
this.occupations.addAll(occupations);
return this;
}
public BuilderExampleBuilder clearOccupations() {
if (this.occupations != null) {
this.occupations.clear();
}
return this;
}
public BuilderExample build() {
// complicated switch statement to produce a compact properly sized immutable set omitted.
Set<String> occupations = ...;
return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
}
@java.lang.Override
public String toString() {
return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
}
}
}
答案 6 :(得分:0)
作为@ CrazyCoder答案的补充,我认为知道这一点非常有用 在Replace Constructor with Builder对话框的右上角,有一个配置按钮,可用于重命名setter的前缀。
答案 7 :(得分:0)
对于那些想要更换&#34;太多参数&#34;使用构建器模式,执行&#34;提取参数对象&#34;然后将转换构造函数转换为此处其他答案中提到的构建器。
答案 8 :(得分:0)
通过右键单击Generate&gt; Constructor类生成类的构造函数。然后,在Windows上,按Ctrl + Shift + A查找操作并键入“builder”,然后选择 “用构建器替换构造函数。”
答案 9 :(得分:0)
在我看来,获取内部静态类而不是单独的最简单方法是:
答案 10 :(得分:0)
我发现Effective Inner Builder是最好的选择,因为它添加了空检查并且可以仅从定义的成员开始。