是否可以从另一个(在同一类中,而不是从子类中)调用构造函数?如果是,怎么办?调用另一个构造函数的最佳方法是什么(如果有几种方法)?


当前回答

有一些设计模式可以满足复杂构造的需要——如果不能简洁地完成,请创建工厂方法或工厂类。

通过最新的java和lambdas的添加,很容易创建一个可以接受任何初始化代码的构造函数。

class LambdaInitedClass {

   public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
       init.accept(this);
   }
}

称之为。。。

 new LambdaInitedClass(l -> { // init l any way you want });

其他回答

是的,有可能:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

    public Foo(int x) {
        this.x = x;
    }
}

要链接到特定的超类构造函数而不是同一类中的构造函数,请使用super而不是this。请注意,您只能链接到一个构造函数,并且它必须是构造函数主体中的第一条语句。

另请参阅这个相关的问题,它是关于C#的,但在相同的原则适用的地方。

从另一个构造函数调用构造函数

class MyConstructorDemo extends ConstructorDemo
{
    MyConstructorDemo()
    {
        this("calling another constructor");
    }
    MyConstructorDemo(String arg)
    {
        System.out.print("This is passed String by another constructor :"+arg);
    }
}

也可以使用super()调用调用父构造函数

它被称为伸缩构造函数反模式或构造函数链接。是的,你肯定可以。我看到了上面的许多示例,我想补充一点,如果你知道你只需要两个或三个构造函数,那可能没问题。但是如果你需要更多,请尝试使用不同的设计模式,如Builder模式。例如:

 public Omar(){};
 public Omar(a){};
 public Omar(a,b){};
 public Omar(a,b,c){};
 public Omar(a,b,c,d){};
 ...

你可能需要更多。在这种情况下,生成器模式将是一个很好的解决方案。这是一篇文章,可能会有所帮助https://medium.com/@型号figuereo/设计图案-2-建筑图案和电梯结构-防图案-60a33de7522e

可以通过this(…)关键字(当需要从同一类调用构造函数时)或super(…)关键词调用另一个构造函数(当您需要从超类调用构造函数时)。

但是,这样的调用必须是构造函数的第一条语句。要克服这个限制,请使用这个答案。

[注:我只想添加一个方面,这是我在其他答案中没有看到的:如何克服this()必须位于第一行的要求的限制。]

在Java中,可以通过this()从构造函数调用同一类的另一个构造函数。但是请注意,这必须在第一行。

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, 0.0);
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }
}

这必须出现在第一行看起来是一个很大的限制,但您可以通过静态方法构造其他构造函数的参数。例如:

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, getDefaultArg3(argument1, argument2));
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }

  private static double getDefaultArg3(double argument1, double argument2) {
    double argument3 = 0;

    // Calculate argument3 here if you like.

    return argument3;

  }

}