David_W (70) [Avatar] Offline
#1
It appears that, in the example, this(accountNumber,false) is actually part of preinitialization, not initialization. For example,

package com.david;

public class Employee extends Person {
static {
System.out.println("static in Employee");
}

public Employee() {
this(test());
System.out.println("Employee ctor");
}

public Employee(int x) {
super(test2());
System.out.println("Employee ctor (int)");
}

private static int test() {
System.out.println("in test");
return 1;
}

private static int test2() {
System.out.println("in test2");
return 1;
}
}
and

package com.david;

public aspect TestInit {
public pointcut EmployeeInit():initialization(Employee.new(..));

public pointcut EmployeePreInit():preinitialization(Employee.new(..));

before():EmployeeInit() {
System.out.println("got employee init");
}

after():EmployeePreInit() {
System.out.println("got employee preinit");
}
}

output is
static in Person
static in Employee
in test
in test2
got employee preinit
Person ctor
got employee init
Employee ctor (int)
Employee ctor

If you change the after():EmployeePreInit() to a before, the output is
static in Person
static in Employee
got employee preinit
in test
in test2
Person ctor
got employee init
Employee ctor (int)
Employee ctor

Note that the preinit message brackets the output for test and test2, so it appears that the explicit this(...) call and the super(...) call are both part of preinit.
ramnivas (171) [Avatar] Offline
#2
Re: error in 3.2.6
Thanks for exploring this subtle issue.

this(accountNumber,false) is in initialization, except for the part that (through the other constructor) calls the base class constructor. That is why I add "from the return
of a parent class’s constructor until the end of the first called constructor." The reason for this implementation is that there is no way to insert byte code to before this().

I will update a sentence to clarify this point.

-Ramnivas
David_W (70) [Avatar] Offline
#3
Re: error in 3.2.6
Where in my example did I call the base class constructor within the this(...) calls?
ramnivas (171) [Avatar] Offline
#4
Re: error in 3.2.6
When you invoked the no-arg constructor, that invoked the other one-arg constructor (through this()), which called super() thus invoking the base class constructor.

public Employee() {
this(test());
System.out.println("Employee ctor");
}

public Employee(int x) {
super(test2());
System.out.println("Employee ctor (int)");
}

Let me know if I misunderstood the question or caused confusion in my explanation.

-Ramnivas
David_W (70) [Avatar] Offline
#5
Re: error in 3.2.6
But test and test2 are static methods in Employee. So I assume that the Employee() constructor order of operations would be:
call test()
call Employee(int x)
call test2()
call super
System.out.println("Employee ctor (int)");
System.out.println("Employee ctor");

so, since the call to super is within the preinitialization, so should the calls to test and test2. In other words, evaluating the parameters to a this(...) call should be evaluated within preinitialization, since this happens before the call to super.
ramnivas (171) [Avatar] Offline
#6
Re: error in 3.2.6
Actually, super call isn't part of preinitialization or initialization (there is no join point for a super() call).

Here are modified aspects and classes:

package com.david;

public aspect TestInit {
public pointcut personInit():initialization(Person+.new(..));

public pointcut personPreInit():preinitialization(Person+.new(..));

before() : personPreInit() {
System.out.println("preinit before advice " + thisJoinPoint.getSignature());
}

after() : personPreInit() {
System.out.println("preinit after advice " + thisJoinPoint.getSignature());
}

before() : personInit() {
System.out.println("init before advice " + thisJoinPoint.getSignature());
}

after() : personInit() {
System.out.println("init after advice " + thisJoinPoint.getSignature());
}
}


package com.david;

public class Employee extends Person {
static {
System.out.println("static in Employee");
}

public Employee() {
this(test());
System.out.println("Employee ctor");
}

public Employee(int x) {
super(test2());
System.out.println("Employee ctor (int)");
}

private static int test() {
System.out.println("in test");
return 1;
}

private static int test2() {
System.out.println("in test2");
return 1;
}
}

package com.david;

public class Person {
static {
System.out.println("static in Person");
}

public Person(int arg) {
System.out.println("In Person(int)");
}
}

Then when I invoke "new Employee()", I get:
static in Person
static in Employee
got employee preinit
preinit before advice com.david.Employee()
in test
in test2
preinit after advice com.david.Employee()
preinit before advice com.david.Person(int)
preinit after advice com.david.Person(int)
init before advice com.david.Person(int)
In Person(int)
init after advice com.david.Person(int)
got employee init
init before advice com.david.Employee()
Employee ctor (int)
Employee ctor
init after advice com.david.Employee()
David_W (70) [Avatar] Offline
#7
Re: error in 3.2.6
Interesting.

The AspectJ documentation defines
initialization(Signature) every initialization of an object when the first constructor called in the type matches Signature, encompassing the return from the super constructor call to the return of the first-called constructor
preinitialization(Signature) every pre-initialization of an object when the first constructor called in the type matches Signature, encompassing the entry of the first-called constructor to the call to the super constructor

Now, since Employee() calls Employee(int), and Employee(int) calls super, preinitialization of Employee should include all joinpoints encountered during the evaluation of the this(...) arguments in Employee() plus all joinpoints encountered during the evaluation of the super(...) arguments in Employee(int).

When running the modified code that you posted, I got output that seems to agree with this:
static in Person
static in Employee
preinit before advice com.david.Employee()
in test
in test2
preinit after advice com.david.Employee()
preinit before advice com.david.Person(int)
preinit after advice com.david.Person(int)
init before advice com.david.Person(int)
In Person(int)
init after advice com.david.Person(int)
init before advice com.david.Employee()
Employee ctor (int)
Employee ctor
init after advice com.david.Employee()

Note that the calls to test and test2 appear between the before and after advice for preinitialization of Employee.

There is no join point for a super call, but the start of execution of the super appears to correspond to after advice for the subclass's preinitialization, or before advice for the super class's preinitialization.

I expect that explaining this in detail in the book might be a bit complicated that early in the book.
ramnivas (171) [Avatar] Offline
#8
Re: error in 3.2.6
> I expect that explaining this in detail in the book might be a bit complicated that early in the book.

This is the key observation.

Writing this chapter has been a balancing act for me (I have significantly edited this about 10 times during the life of second edition). On one hand, I can get really comprehensive and include many more details. At some point, I did indeed had a version with many more details. However, I got overwhelming feedback that many of the details could interest only to the academic community and can turn away practitioner. That caused me to slim down (it was a struggle!!) content by almost 10 pages and add
"Although I cover a fair amount of detail in this section, I’m limiting my coverage to practical uses. For more in-depth semantics, refer to the AspectJ Programming Guide available from AspectJ’s web site (http://www.eclipse.org/aspectj/docs.php)."

-Ramnivas