如何避免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; } }