Call to another constructor must be the first statement in constructor block

I am confused why the following pattern’s call to the other constructor block does not count as the first statement in the constructor block:

public class MyClass
{
    final String someProperty;
    public MyClass()
    {
        /* some default logic */
    }
    public MyClass(String someProperty)
    {
        this().someProperty = someProperty;
    }
}

It seems to me like the order of operations should be:

  1. The empty constructor runs.
  2. The property gets assigned.

However, I get a compile error:

Call to another constructor must be the first statement in constructor block

Edits

I realize that I can just separate the calls.

public MyClass(String someProperty)
{
    this();
    this.someProperty = someProperty;
}

However, it sure would be nice to be able to one-line this constructor chaining. I am trying to understand why this() behaves differently than new MyClass(). They both run the empty constructor! But they allow for different behavior after the constructor completes. Note that I can chain directly off the constructor when using the fluent pattern.

new MyClass().doSomeStuff().doOtherStuff();

Answer

I think this speaks somewhat to Apex inheriting so much from Java.

Try the same thing with a Java compiler:

public class HelloDog
{
  public static void main(String[] args)
  {
    Dog myDog = new Dog();
    System.out.print(myDog);
  }
}

class Dog{
    protected String name;

    public Dog(){
        this("Fido").name="Arf"; 
        //this.name="Arf";
        System.out.println("Inside no argument constructor of Dog class");
    }

    public Dog(String name){
        this.name = name;
        System.out.println("One arg constructor of Dog class");
    }
}

Gives the following compiler errors:

/HelloDog.java:15: error: call to this must be first statement in constructor

this("Fido").name="Arf";
. ^

/HelloDog.java:15: error: void cannot be dereferenced
this("Fido").name="Arf";
. ^

As Martin answered, the chained constructor returns void rather than the instance, so you can’t chain anything to it.

Calling the constructor and constructor chaining are two different things with very similar syntax.

Personally I think the C# syntax makes constructor chaining clearer. Rather than being a special case of this that appears at the start of the constructor it has it’s own explicit syntax:

class Dog {
    protected String name;

    public Dog() : this("Fido")
    {
    }

    public Dog(String name){
        this.name = name;
    }
}

If you tried to do a public Dog() : this("Fido").name="arf" { in C# the compiler will look at you funny and ask where the missing { is. The constructor chaining here isn’t a statement that can end in a semicolon. It’s telling the compiler to chain the constructors together.

Attribution
Source : Link , Question Author : Adrian Larson , Answer Author : Daniel Ballinger

Leave a Comment