如何避免Java中的构造器代码冗余?
我有以下class级:
class Pair { String car; Integer cdr; public Pair () {} public Pair (String car) { this.car = car; } public Pair (Integer cdr) { this.cdr = cdr; } public Pair (String car, Integer cdr) { this(car); this(cdr); } }
该类包含两个可选的值,我想提供所有可能的构造器排列。 第一个版本不初始化,第二个只初始化第一个值,第三个只初始化第二个值。
最后一个构造函数是第二个和第三个的组合。 但是不可能写下来,因为代码失败。
constructor.java:13:对此的调用必须是构造函数中的第一条语句 此(CDR); ^ 1错误
是否有可能编写最后的构造函数没有任何代码冗余(也没有调用相同的setter方法)?
通常,具有较less参数的构造函数应该更多地调用这些构造函数。
public Pair() {} public Pair(String car) { this(car, null); } public Pair(Integer cdr) { this(null, cdr); } public Pair(String car, Integer cdr) { this.car = car; this.cdr = cdr; }
链接你的构造函数的方向相反,最具体的是设置所有的字段:
public Pair() { this(null, null); // For consistency } public Pair(String car) { this(car, null); } public Pair(Integer cdr) { this(null, cdr); } public Pair (String car, Integer cdr) { this.car = car; this.cdr = cdr; }
那样:
- 只有一个地方设置字段,并设置所有的字段
- 从其他任何构造函数中,您可以指定(并告诉您何时读取代码)其他字段的“默认”值。
另外,我强烈build议你将字段设置为私有的(也许是最终的),并给它们更有意义的名称。
注意这样,如果你有5个参数,一个构造函数有3个,一个有4个,另一个有5个,你可以select连接3 – > 4 – > 5,也可以直接从3 – > 5。
此外,您可能希望完全移除单参数构造函数 – 而是使用静态方法更具可读性,您可以在其中指定名称中的含义:
public static Pair fromCar(String car) { return new Pair(car, null); } public static Pair fromCdr(Integer cdr) { return new Pair(null, cdr); }
或者按照我的意思命名:
public static Pair fromFirst(String first) { return new Pair(first, null); } public static Pair fromSecond(Integer second) { return new Pair(null, second); }
此时,您可以使Pair
类成为generics,而不用担心如果两个types参数相同,哪个构造函数将被调用。 另外,读取代码的任何人都可以理解将构造什么,而不必检查参数的types。
您可能正在寻找这里的build设者模式 。
除此之外,这种模式可以让你不要有一个bazillion的构造函数来覆盖所有的情况。 对于你的情况,这可能是:
@Immutable // see JSR 305 public final class Pair { private final String car; private final integer cdr; private Pair(final Builder builder) { car = builder.car; cdr = builder.cdr; } public static Builder newBuilder() { return new Builder(); } // whatever other methods in Pair, including accessors for car and cdr, then: @NotThreadSafe // see JSR 305 public final class Builder { private String car; private int cdr; private Builder() { } public Builder withCar(final String car) { this.car = car; return this; } public Builder withCdr(final int cdr) { this.cdr = cdr; return this; } public Pair build() { return new Pair(this); } } }
示例用法:
final Pair newPair = Pair.newBuilder.withCar("foo").withCdr(1).build();
优点: Pair
现在是不可改变的!
class Pair { String car; Integer cdr; public Pair () {} public Pair (String car) { this(car, null) } public Pair (Integer cdr) { this(null, cdr); } public Pair (String car, Integer cdr) { this.car = car; this.cdr = cdr; } }