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));
}
我有一个 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));
}