Chaining Constructors in Java

98 views Asked by At

Could not came up with better title.

A classic learning example: class Human, where properties are name, age, mother and father. Both parents are Human as well.

public class Human {
    String name;
    int age;
    Human mother;
}

I want to create 3 constructors:

  1. Human();
  2. Human(String name, int age);
  3. Human(String name, int age, Human mother).

I guess I do understand how the chaining works, and that's what I did:

Human() {
    this("Jack", 22);
}

Human(int age, String name) {
    this(age, name, new Human()); // new Human() will cause SOF Error.
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

As mentioned above, I receive StackOverflowError, once again I guess I know why it happened. Although to be fair I thought I will get something like Human Jack where his mother is also Human Jack.

Nevertheless, I wonder how should it be done. My guess is that instead of new Human() I should call the constructor with all parameters, but I'm not sure if it's true and the only option available.

Will appreciate any guidance here.

5

There are 5 answers

1
T.J. Crowder On BEST ANSWER

Yes, you're right about why it happens. Just to be sure, though:

  • new Human() calls this("Jack", 22)
  • this("Jack", 22) calls this(age, name, new Human())
  • The new Human() in that calls this("Jack", 22) again
  • which calls this(age, name, new Human()) again
  • until you run out of stack

The right way to do it is to ensure that you don't end up back where you started. So if you use new Human(String) or new Human(String, int) in any of your constructors, you have to be sure that that constructor (new Human(String) or new Human(String, int)) doesn't also use new Human(String) or new Human(String, int), since you'll end up endlessly recursing. You need to use new Human(String, int, Human) somewhere. So for instance:

Human(int age, String name) {
    this(age, name, null);
}

Of course, that means the new instance will have null for mother.

0
Ravindra Gupta On
Human() {
    this.name = "Jack";
    this.age = 22;
}

Human(int age, String name) {
    this.age = age;
    this.name = name;
    this.mother = null;
}

Human(int age, String name, Human mother) {
    this.age = age;
    this.name = name;
    this.mother = mother;
}

This will not create any hirarical or nested constructor

1
Devs love ZenUML On

If I understand your question correctly, there are two sub-questions:

  1. Is there a different way to do it in Java language (with constructors)?
  2. Is there a better way to do it in Object-Oriented Design?

Re the first question, a constructor is a method, your implementation results in two recursive methods. You have to break the recursive or introduce an exiting condition. There is another option - call this(age, name, null) in the first constructor.

Re the second question, a popular solution is the simple factory pattern, where you just have one private constructor with all parameters, and then a few public factory methods to do whatever you want.

1
Arne Burmeister On

Your constructor Human(int, String) does a recursion without any condition which at the end creates a StackOverflowError.

Constructor overloading is a very common way to provide convenient ways to create an object. As long as the members are not final and may be manipulated later, you should better pass no value (aka null) instead of creating more objects on the fly.

In reality there is no human without a mother but it may be unknown so passing null for now would be the better approach here.

If you need the mother immutable you must not provide any constructor without a reference for the mother to make this clearly visible. Even this will not work as you cannot provide such an endless tree structure to the beginning of mankind. Typically such structures have a "root" object which does not have a parent (or mother in this example).

2
Pratik On

I would suggest instead of going to constructor chaining. I would prefer to go for instance variable chaining and use builder design pattern along with node kind of data structure.

Class Human{
int age;
Sting name;
Human mother;

public  Human setAge(int age){
this.age = age;    
return this;
}

public Human setName(String name){
this.name = name;
return this;
}

public Human setHuman(Human mother){
this.mother= mother;
return this;
}

}

After doing this you can create first Mother instance as human and then set as a human in child. let me know for more specific answer.