Java 中的构造函数重载 - 最佳实践

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

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

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

谢谢:)


答案 1

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

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极客称之为协作者),请考虑以下两件事之一:

创建参数类

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());
}

...或创建一个属性:SimpleParams

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

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

这方面的一个示例可能是 - 主构造函数采用(加上列和选择模型),而其他构造函数调用此主构造函数。JTableTableModel

对于超类已经具有重载构造函数的子类,我倾向于假设将任何父类的构造函数视为构造函数是合理的,并认为没有单个主构造函数是完全合法的。例如,在扩展时,我经常提供3个构造函数,一个只获取消息,一个获取原因,另一个同时获取两者。这些构造函数中的每一个都直接调用。ExceptionStringThrowablesuper