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



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

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

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

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/

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

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.asListhttps://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));
}

最新更新