huateng
huateng

Reputation: 13

java constructor order

This java program is easy and full of comment,so you can understand it fast.however,why in construct staff[1],the program first go to the statement:

this("Employee #" + nextId, s);

then go to the object initialization block,and then go back to the statement,how confusion.why not it first use the object initialization block

import java.util.*;

public class ConstructorTest
{
   public static void main(String[] args)
   {
      // fill the staff array with three Employee objects
      Employee[] staff = new Employee[3];

      staff[0] = new Employee("Harry", 40000);
      staff[1] = new Employee(60000);
      staff[2] = new Employee();

      // print out information about all Employee objects
      for (Employee e : staff)
         System.out.println("name=" + e.getName()
            + ",id=" + e.getId()
            + ",salary=" + e.getSalary());
   }
}

class Employee
{
   // three overloaded constructors
   public Employee(String n, double s)
   {
      name = n;
      salary = s;
   }

   public Employee(double s)
   {
      // calls the Employee(String, double) constructor
      this("Employee #" + nextId, s);
   }

   // the default constructor
   public Employee()
   {
      // name initialized to ""--see below
      // salary not explicitly set--initialized to 0
      // id initialized in initialization block
   }

   public String getName()
   {
      return name;
   }

   public double getSalary()
   {
      return salary;
   }

   public int getId()
   {
      return id;
   }

   private static int nextId;

   private int id;
   private String name = ""; // instance field initialization
   private double salary;

   // static initialization block
   static
   {
      Random generator = new Random();
      // set nextId to a random number between 0 and 9999
      nextId = generator.nextInt(10000);
   }

   // object initialization block
   {
      id = nextId;
      nextId++;
   }
}

Upvotes: 0

Views: 4088

Answers (4)

Ernest Friedman-Hill
Ernest Friedman-Hill

Reputation: 81694

The Java compiler must ensure that the code in the object initialization block is called from each constructor. For most constructors, it does this by inserting the code into the constructor right after the implicit or explicit call to super(). For compilers that start with this(), however, first of all there is no implicit call to super() -- the other constructor handles that. Secondly, in such a constructor the object initializer block can't be inserted at all, since the code will be picked up when the second constructor is called. Therefore the this() call is the very first thing that happens.

Upvotes: 0

pap
pap

Reputation: 27614

Not sure what the actual question is, it's a bit confusing. The order of initialization (static, object, constructor) is predefined and has nothing to do with in which order they appear in the code. As for the general style, I generally discourage using object initialization blocks. It's a very common source of errors, it makes exception-handling more complex and it's hard to debug. In addition, it's not a very common pattern so developers tend to miss looking for it when analyzing bugs.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500795

This follows the order specified in section 8.8.7.1 of the JLS:

(Final two bullets)

Let C be the class being instantiated, let S be the direct superclass of C, and let i be the instance being created. The evaluation of an explicit constructor invocation proceeds as follows:

  • First, if the constructor invocation statement is a superclass constructor invocation, (Snipped because it's not in our case)
  • Next, the constructor is invoked.
  • Finally, if the constructor invocation statement is a superclass constructor invocation and the constructor invocation statement completes normally, then all instance variable initializers of C and all instance initializers of C are executed. (Snip) An alternate constructor invocation does not perform this additional implicit action.

So the instance initializer is executed immediately after the superconstructor is called - which is (implicitly) from public Employee(String n, double s). This should happen before the body of that two-parameter constructor is executed.

Upvotes: 1

Michael Borgwardt
Michael Borgwardt

Reputation: 346317

Because this("Employee #" + nextId, s); includes an implicit call to the superclass constructor, which of course must be executed before the initializer block of the subclass.

Using instance initializers is generally a bad idea as they are not well known, cannot do anything more than constructors, and mixing both leads to confusion.

Upvotes: 4

Related Questions