Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免Java中的构造函数代码冗余?_Java - Fatal编程技术网

如何避免Java中的构造函数代码冗余?

如何避免Java中的构造函数代码冗余?,java,Java,我有以下课程: 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);

我有以下课程:

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: call to this must be first statement in constructor this(cdr); ^ 1 error java:13:对这个函数的调用必须是构造函数中的第一条语句 这个(cdr); ^ 1错误
是否可以在没有任何代码冗余的情况下编写最后一个构造函数(也不调用相同的setter方法)?

通常,参数较少的构造函数应该调用参数较多的构造函数

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;
}
这样:

  • 只有一个位置设置字段,它设置所有字段
  • 从任何其他构造函数中,可以指定(并在读取代码时告知)其他字段的“默认”值
另一方面,我强烈建议您将字段设置为私有字段(可能是最终字段),并为它们指定更有意义的名称

注意,通过这种方式,如果你有(比如)5个参数,一个构造函数有3个,一个构造函数有4个,一个构造函数有5个,你可以选择从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);
}

此时,您可以将
类设置为泛型,而不必担心如果两个类型参数相同,将调用哪个构造函数。此外,任何阅读代码的人都可以理解将要构造的内容,而不必检查参数的类型。

您可能正在此处查找

除此之外,此模式允许您不必拥有覆盖所有情况的大量构造函数。对于您的情况,这可能是:

@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
现在是不可变的

一个选项是将字段设置为final,并让默认构造函数调用this(null,null)构造函数调用其父级规则的例外是final变量。对于带有最终变量的Pair版本,代码如下:
类Pair{private final String car;private final Integer cdr;public Pair(){this.car=null;this.cdr=null;}公共Pair(String car){this.car=car;this.cdr=null;}…}
@MichaelShopsin为什么会有exception@MichaelShopsin一个建造师想,我要把最后的作品链接起来一个方法。@josefx你是对的,我从来没有尝试过只调用其他构造函数的方法。@ceving:在Java上下文中,这似乎是一个相当模糊的意思。。。特别是因为它们是运算符而不是值。如果这些只是“第一”和“第二”值,那么这些名称对大多数人来说会更有意义。伙计们,我觉得讨论
car
cdr
的命名真的是离题了,这里有点吵;-)这只是一个例子。如果您更熟悉它们,我可以将其更改为
foo
bar
。@ceving:正如Jon所说,最好将它们重命名为
first
second
。这里有一个2元组,而不是cons单元格。对于构建器模式来说,这是一个很好的全面示例,但在本例中可能有点过头了。(而且,我认为不变性并不自动成为优势)。但仍然+1是一个不错的选择@我已经习惯了这样做,另一方面,我可能会错过一些要点。。。例如,DI框架(依赖注入)。this()和super()的问题必须是[构造函数中的第一条语句][1]。[1] :调用this(…)构造函数两次,只能让一个构造函数调用另一个构造函数,链式构造函数调用必须是构造函数中的第一条语句。
final Pair newPair = Pair.newBuilder.withCar("foo").withCdr(1).build();