重载构造函数调用其他构造函数,但不作为第一个语句

Dav*_*d B 17 java constructor overloading

我在java中使用多个构造函数时遇到了一些麻烦.

我想做的是这样的:

public class MyClass {

 // first constructor
 public MyClass(arg1, arg2, arg3) {
  // do some construction
 }

 // second constructor
 public MyClass(arg1) {
      // do some stuff to calculate arg2 and arg3
      this(arg1, arg2, arg3);
    }
}
Run Code Online (Sandbox Code Playgroud)

但我不能,因为第二个构造函数不能调用另一个构造函数,除非它是第一行.

这种情况的常见解决方案是什么?我无法计算arg2和arg3"在行".我想可能会创建一个构造辅助方法,它将进行实际构造,但我不确定它是如此"漂亮"......

编辑:使用辅助方法也有问题,因为我的一些字段是最终的,我不能使用辅助方法设置它们.

Mat*_*ell 24

Typically use another common method - a "construction helper" as you've suggested.

public class MyClass { 

    // first constructor 
    public MyClass(arg1, arg2, arg3) { 
      init(arg1, arg2, arg3); 
    } 

    // second constructor 
    public MyClass(int arg1) { 
      // do some stuff to calculate arg2 and arg3 
      init(arg1, arg2, arg3); 
    } 

    private init(int arg1, int arg2, int arg3) {
      // do some construction 
    }
} 
Run Code Online (Sandbox Code Playgroud)

The alternative is a Factory-style approach in which you have a MyClassFactory that gives you MyClass instances, and MyClass has only the one constructor:

public class MyClass { 

    // constructor 
    public MyClass(arg1, arg2, arg3) { 
      // do some construction 
    } 
} 

public class MyClassFactory { 

    public static MyClass MakeMyClass(arg1, arg2, arg3) { 
      return new MyClass(arg1, arg2, arg3);
    } 

    public static MyClass MakeMyClass(arg1) { 
      // do some stuff to calculate arg2 and arg3 
      return new MyClass(arg1, arg2, arg3);
    } 
} 
Run Code Online (Sandbox Code Playgroud)

I definitely prefer the first option.

  • 如果你将工厂方法放在类本身而不是在不同的类中,我肯定更喜欢第二种选择.第一个选项不允许您使用参数值"final"创建分配的字段.编译器不能告诉`init`方法在每个构造函数中被调用一次,并且永远不会在构造函数之外.如果您不喜欢工厂方法,请参阅我的答案,了解有关计算其他参数的其他选项. (3认同)
  • 有时可以使用抛出异常的选项,而从构造函数中抛出异常是一种坏习惯。对于这些情况,工厂方法更好 (2认同)

Gai*_*aim 9

下一个可能的解决方案是工厂方法.这些静态方法可以重载,计算后可以调用private/protected构造函数

public class MyClass {

    private MyClass( arg1, arg2, arg3 ) {
         // do sth
    }

    public static MyClass getInstance( arg1 ) {
         // calculate arg2,3
        return new MyClass( arg1, arg2, arg3 );
    }

    public static MyClass getInstance( arg1, arg2, arg3 ) {
        return new MyClass( arg1, arg2, arg3 );
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:当您有最终字段时,此方法也是理想的


Jor*_*orn 8

虽然我更喜欢其他几个答案指出的工厂方法选项,但我想建议另一个选项:您可以使用静态方法来计算其他参数:

public class MyClass {
    public MyClass(int arg1, int arg2, int arg3) {
        // do some construction
    }

    public MyClass(int arg1) {
      //call to this() must be the first one
      this(arg1, calculateArg2(arg1), calculateArg3());
      //you can do other stuff here
    }

    private static int calculateArg2(int arg1) {
      //calc arg2 here
    }

    private static int calculateArg3() {
      //calc arg3 here
    }
}
Run Code Online (Sandbox Code Playgroud)