Phoenix
Phoenix

Reputation: 8923

Why can't I call the default constructor from a parameterized constructor inside a private class?

public class Graph {

    private Node node;

    public void createGraph()
    {

    }

    private class Node<K>{
        K data;
        List<Node> adjacent;
        boolean visited; 

        Node()
        {
            adjacent = new ArrayList<Node>();
            visited = false;
        }

        Node(K data)
        {
            this.data = data;
            this.Node();

        }

    }



}

Why is the compiler complaining that I can't call this.Node() ?

Upvotes: 1

Views: 2652

Answers (4)

dcernahoschi
dcernahoschi

Reputation: 15230

Try:

 Node(K data)
    {
        this();
        this.data = data;

    }

The call to the "other" constructor needs to be always first. The call to the other constructors from inside a constructor is always done with this(...) not with Node(...).

JLS section 8.8.7 specify how the constructor body should look like:

ConstructorBody: { ExplicitConstructorInvocation(opt) BlockStatements(opt) }

where ExplicitConstructorInvocation(opt) is either an alternate constructor or a constructor from the parent class invoked with super(...).

and JLS section 12.5 specify the object initialization steps when a constructor is called:

Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:

  • Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  • If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps.

...

These JLS rules make sure that the parent class constructor is called first and once.

Upvotes: 8

SLaks
SLaks

Reputation: 887275

You can only ever call another constructor as the first statement in the current constructor.

Move this.data = data; below this().

Upvotes: 6

Bal&#225;zs &#201;des
Bal&#225;zs &#201;des

Reputation: 13807

When i need to create more constructors, i do it this way (assuming, the set of parameters would only expand, and not change entirely):

public class Foo
{
    private static final int DEFAULT_SECOND = ...;
    private static final int DEFAULT_FIRST = ...;

    //Constructor with the biggest attribute set
    public Foo(int first, int second)
    {
        //do the actual initialization
    }

    public Foo(int first)
    {
        this(first, DEFAULT_SECOND);
    }

    public Foo()
    {
       this(DEFAULT_FIRST, DEFAULT_SECOND);
    }  
}

Upvotes: 0

Platinum Azure
Platinum Azure

Reputation: 46183

In order to invoke a constructor within another one:

  1. You must invoke it with this(args).
  2. You must invoke it as the first statement in the constructor.

    Node(K data) {
        this();
        this.data = data;
    }
    

Upvotes: 2

Related Questions