Java:多个构造函数强制代码重用?

Java: Multiple constructors forcing code reuse?

我有一个 class,其中一个成员是 ArrayList<ArrayList<Double>> elements,所以我有一个采用相同类型的构造函数,一切都很好。

public elementArray(ArrayList<ArrayList<Double>> elements)
{
    this.elements =  elements;
    // a bunch of other stuff happens
}

但是,我也需要能够用Double[][]类型的输入进行构造,所以我先将其转换为二维列表类型,然后调用原始构造函数...

public elementArray(Double[][] array)
{
    // convert Double[][] array to ArrayList<ArrayList<Double>> elements
    this(elements);
}

只是,我不能调用另一个构造函数,除非是在我的构造函数中发生的第一件事!我是注定要在这里复制粘贴,还是有什么聪明的方法可以做我想做的事?

一种解决方案是将转换提取到静态方法中:

public elementArray(Double[][] array) {
    this(convert(elements));
}

private static ArrayList<ArrayList<Double>> convert(Double[][] array) {
    // convert Double[][] array to ArrayList<ArrayList<Double>> elements
}

调用前不能有代码this(),也不能调用其他实例方法。

您可以将该转换提取到单独的静态方法中:

private static ArrayList<ArrayList<Double>> arrayToList(Double[][] d) {
    //convert and return list
}

并在您的第二个构造函数中重用此方法:

public elementArray(Double[][] array) {
    this(arrayToList(array));
}

一种常见的使用模式是改用生成器。

https://iluwatar.github.io/java-design-patterns/patterns/builder/

或者静态工厂方法。

https://iluwatar.github.io/java-design-patterns/patterns/factory-method/

例如使用静态工厂方法,您将只有一个(可能是私有的)构造函数,它接受您的 class 需要的最原始版本。

public class elementArray{
    public elementArray(ArrayList<ArrayList<Double>> elements)
    {
        this.elements =  elements;
        // a bunch of other stuff happens
    }
    public static elementArray create(Double[][] array)
    {
        // convert Double[][] array to ArrayList<ArrayList<Double>> elements
        return new elementArray(elements);
    }
    public static elementArray create(ArrayList<ArrayList<Double>> elements)
    {
        return new elementArray(elements);
    }
}

然后,您将调用静态方法而不是调用构造函数。

elementArray.create(new double[][]{{1.0d},{2.0d}});

这在最近 Java、Guava 和 Java 标准库中使用得相当普遍。

参见 Arrays.asList https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList-T...-

但是最好用List代替ArrayList

    public elementArray(Double[][] array) {
        this(convert(elements));
    }

    static ArrayList<ArrayList<Double>> convert(Double[][] elements) {
        return IntStream.range(0, elements.length)
                .mapToObj(i -> IntStream.range(0, elements[i].length)
                        .mapToObj(j -> elements[i][j])
                        .collect(ArrayList::new, List::add, (u, v) -> u.addAll(v)))
                .collect(ArrayList::new,
                        (u, v) -> v.add(u),
                        (u, v) -> u.addAll(v));
    }