问题

有一些类似的主题,但我找不到一个有足够答案的主题。

我想知道在Java中构造函数重载的最佳实践是什么。我已经对这个问题有了自己的想法,但我想听听更多建议。

我指的是简单类中的构造函数重载和构造函数重载,同时继承已经重载的类(意味着基类具有重载的构造函数)。

谢谢 :)


#1 热门回答(150 赞)

虽然没有"官方指南",但我遵循KISS和DRY的原则。使重载的构造函数尽可能简单,最简单的方法是它们只调用它(...)。这样你只需要检查和处理一次参数一次。

public class Simple {

    public Simple() {
        this(null);
    }

    public Simple(Resource r) {
        this(r, null);
    }

    public Simple(Resource r1, Resource r2) {
        // Guard statements, initialize resources or throw exceptions if
        // the resources are wrong
        if (r1 == null) {
            r1 = new Resource();
        }
        if (r2 == null) {
            r2 = new Resource();
        }

        // do whatever with resources
    }

}

从单元测试的角度来看,测试类很容易,因为你可以将资源放入其中。如果该类有许多资源(或者像OO-geeks那样调用它的协作者),请考虑以下两种情况之一:

##创建一个参数类

public class SimpleParams {
    Resource r1;
    Resource r2;
    // Imagine there are setters and getters here but I'm too lazy 
    // to write it out. you can make it the parameter class 
    // "immutable" if you don't have setters and only set the 
    // resources through the SimpleParams constructor
}

Simple中的构造函数只需要拆分SimpleParams参数:

public Simple(SimpleParams params) {
    this(params.getR1(), params.getR2());
}

...或makeSimpleParamsan属性:

public Simple(Resource r1, Resource r2) {
    this(new SimpleParams(r1, r2));
}

public Simple(SimpleParams params) {
    this.params = params;
}

##做一个工厂课

创建一个为你初始化资源的工厂类,如果初始化资源有点困难,这是有利的:

public interface ResourceFactory {
    public Resource createR1();
    public Resource createR2();
}

然后以与参数类相同的方式完成构造函数:

public Simple(ResourceFactory factory) {
    this(factory.createR1(), factory.createR2());
}

##将两者结合起来

是的...你可以根据当时更容易的方式混合和匹配两种方式。参数类和简单的工厂类几乎是相同的,考虑到它们以相同的方式使用它们.Simple类。


#2 热门回答(71 赞)

我认为最好的做法是让单个主构造函数,重载的构造函数通过调用相关参数默认值来调用this()来引用它。这样做的原因是它使得对象的构造状态变得更加清晰 - 实际上你可以将主要构造函数看作是唯一真正的构造函数,其他人只是委托给它

其中一个例子可能是JTable-主构造函数采用aTableModel(加上列和选择模型),其他构造函数调用此主构造函数。

对于超类已经重载了构造函数的子类,我倾向于认为处理任何父类的构造函数是非常合理的,并认为没有一个主构造函数是完全合法的。例如,当扩展Exception时,我经常提供3个构造函数,一个只需要aString消息,一个服用Throwablecause而另一个服用两者。这些构造函数中的每一个都直接调用super


#3 热门回答(6 赞)

如果你有一个非常复杂的类,其中包含许多选项,其中只有一些组合有效,请考虑使用Builder。在代码方面也很有效但在逻辑上也很好。

Builder是一个嵌套类,其方法仅用于设置字段,然后ComplexClass构造函数仅将此类构建器作为参数。

编辑:ComplexClass构造函数可以确保Builder中的状态有效。如果你只是在ComplexClass上使用setter,这很难做到。


原文链接