当前位置: 首页 > 知识库问答 >
问题:

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

东方和煦
2023-03-14

我有以下课程:

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

是否可以在没有任何代码冗余的情况下(也不调用相同的setter方法)编写最后一个构造函数?

共有3个答案

田嘉澍
2023-03-14

您可能正在这里寻找构建器模式。

除此之外,这种模式允许您不使用覆盖所有情况的无数构造函数。对于您的情况,这可能是:

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

卫松
2023-03-14

将您的构造函数链接到相反的方向,最具体的是设置所有字段的构造函数:

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链接-

此外,您可能希望完全删除单参数构造函数——使用静态方法更具可读性,您可以指定名称中的含义:

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类泛型,而不用担心如果两个类型参数相同,将调用哪个构造函数。此外,任何阅读代码的人都可以理解将构造什么,而不必检查参数的类型。

杨俊茂
2023-03-14

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

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; }
 类似资料:
  • 问题内容: 我有一个客户端库,在该客户端库中对我的REST服务进行http远程调用,然后返回给客户,该客户正在调用我的库,其中包含从REST服务获得的响应以及所有错误(如果包装了任何错误)围绕对象。 这是我的枚举类: 这是我的枚举类: 如您所见,在我的课堂上我有很多领域,因此我有一个很长的构造器,每次当我做一个对象的时候都会有很大的联系。将来我可能会有更多的字段,但目前只有这些字段。 有什么更好的

  • 问题内容: 我发现我的构造函数开始看起来像这样: 不断增加的参数列表。由于“容器”是我的依赖项注入容器,所以为什么我不能这样做: 每堂课?不利之处是什么?如果执行此操作,则感觉就像我在使用精美的静态方法。请分享你对IoC和依赖注入疯狂的想法。 问题答案: 正确的是,如果将容器用作服务定位器,则它或多或少是光荣的静态工厂。由于种种原因,我认为这是一种反模式。 构造函数注入的奇妙好处之一是,它使违反单

  • 我是Java的新手,正在处理一个家庭作业问题。该问题指定使用一个构造函数创建一个Temperature类,该构造函数接受华氏温度(作为double)并将其存储在字段中。setFahrenheit方法接受一个华氏温度(以双倍数形式),并将其存储在字段中。 这在我看来是多余的。setFahrenheit方法不是和构造函数完全一样吗?

  • 我不清楚它写在哪里 私有构造函数的存在是为了避免将复制构造函数实现为此(p.x,p.y)时出现的争用条件;这是私有构造函数捕获习惯用法的一个例子(Bloch和Gafter,2005)。 我知道它提供了一个getter来在数组中同时检索x和y,而不是为每一个单独的getter,所以调用者将看到一致的值,但为什么是私有构造函数呢?这里有什么诀窍

  • 我需要重构现有的抽象类来实现依赖注入,但是这个类有两个接受其他参数的构造函数。 我需要注入一些接口,并避免在构造函数中传递任何其他参数,如“settingsId”和“Setting”。所以我的想法是在创建此类的实例后创建两种方法来设置这些参数。 但它看起来不是一个合适的解决方案,因为如果开发人员忘记在创建实例后运行这些方法之一,我们将来可能会得到一个异常(对象未设置为引用...)。我应该如何正确执

  • Lodash castArray函数没有任何特殊之处。有没有什么方法可以在没有任何外部库的情况下,利用最新的语言功能解决这个问题,但时间很短? 如果您不熟悉该任务: 有没有办法在没有类型检查的情况下做到这一点?请注意,我寻找最短的等效物ES6。