I'm having some trouble using multiple constructors in java.
what I want to do is something like this:
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);
}
}
but I can't, since the second constructor cannot call another constructor, unless it is the first line.
What is the common solution for such situation? I can't calculate arg2 and arg3 "in line". I thought maybe creating a construction helper method, that will do the actual construction, but I'm not sure that's so "pretty"...
EDIT: Using a helper method is also problematic since some of my fields are final, and I can't set them using a helper method.
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
}
}
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);
}
}
I definitely prefer the first option.
Next possible solution is Factory method. These static methods can be overloaded and after calculation they can call the private / protected constructor
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 );
}
}
EDIT: This method is also ideal when you have a final fields
Although I prefer the factory method option pointed to by several other answers, I wanted to suggest another option: You can use static methods to do the calculation of your other parameters:
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
}
}
The helper and factory options are very good.
There is another one:
public MyClass(int arg1) {
this(arg1, calculateArg2(), calculateArg3());
}
private static int calculateArg2() {..}
private static int calculateArg3() {..}
Use marker values for 'missing'
public class MyClass {
public MyClass(arg1, arg2, arg3) {
// do some stuff to calculate arg2 and arg3 if they are the missing values
// do some construction
}
public MyClass(arg1) {
this(arg1, null, null);
}
}
For best results, make the 'general' constructor protected or private.
Another way is this:
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
doSomeStuffToArg3Arg3(arg2, arg3)
}
// second constructor
public MyClass(int arg1) {
this(arg1, arg2, arg3);
}
private void doSomeStuffToArg3Arg3(int arg2, int arg3) {
// do some stuff to calculate arg2 and arg3
}
}
You can move the code of MyClass(arg1, arg2, arg3) into helper method (name it Init or something else ) and then call this method in both constructors.
As an alternative to the answers given, the simplest way is to refactor the argument calculation to the 3 argument constructor;
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
if (null == arg2) {
// calculate arg2
}
if (null == arg3) {
// calculate arg3
}
// do some construction
}
// second constructor
public MyClass(arg1) {
this(arg1, null, null);
}
}
You could create a factory method which calls the constructor:
public class MyClass {
// first constructor
public MyClass(arg1, arg2, arg3) {
// do some construction
}
// second constructor as factory method
public static createMyClassAndDoFunkyStuff(int arg1) {
// do some stuff to calculate arg2 and arg3
return new MyClass(arg1, arg2, arg3);
}
}
来源:https://stackoverflow.com/questions/3386136/overloaded-constructor-calling-other-constructor-but-not-as-first-statement