Reputation: 27702
I was collecting design paterns for a personal cheat sheet and I found a, at least for me, strange piece of code at Head First Design Patterns (By Eric Freeman, Elisabeth Robson, Bert Bates, Kathy Sierra).
I don't think I am allowed to post here the piece of code exactly at is written in the book but I will reproduce the code that shocked me:
Assuming we have previously deffined the class A
with a public method runSomeCode(), then we have class B as follows:
public class B {
A a;
A b;
A x = a;
public B() {
a = new A();
b = new A();
}
public void testB()
{
x.runSomeCode();
}
}
My first impression looking at this code is that any call to a B instance testB method should throw a NullPointerException
but I couldn't imagine they would had published such a mistake.
If the book is right then I understand that
x = a;
must be done at the end of B constructor execution but I am still surprised by this sintaxis and my questions are:
EDIT THis is the book example:
The case I am concerned about is when numberGumballs = 0;
EDIT II
I think I know what happened with the example.
In the book, the referenced classes are NOT declared static but few minutes ago I thought it could compile if A was static. So, maybe, the book authors got the code from a larger project where static classes were being used. So I tried this and, this time, it does work but the example seems to continue being wrong and the following code doesn't make any sense concerning State pattern.
public class B {
public static class Base {
public static void runSomeCode() { System.out.println("Base!"); }
}
public static class A extends Base {
public static void runSomeCode() { System.out.println("A!"); }
};
A a;
A b;
A x = a;
public B() {
a = new A();
b = new A();
}
public void testB()
{
x.runSomeCode();
}
}
Yet Another Edit
It seems I have not been the first one to notice this problem in the book example, at O'Reilly site errata section, under unconfirmed erratas sub-section you can find:
Upvotes: 3
Views: 1343
Reputation: 3641
When you first create an object of type B, the fields that have any initializations are initialized first. So, A x = a;
is executed first, even before the code in the constructor is executed which sets the value of x to null, since a has not been instantiated and is just a null reference of type A. After this, the following code is executed which creates the two objects.
public B() {
a = new A();
b = new A();
}
x is still null at this point. So when you try to execute a method in A class using x, it will throw a null pointer exception.
Upvotes: 1
Reputation: 2124
To answer your questions:
x
into the constructor. Having it as a field initializer has no benefits that would be obvious to me.What's supposed to be the point of this "pattern"? You just end up with two references where one would have done...why not just use a
instead?
Upvotes: 1
Reputation: 2459
Am I wrong?
In-place variable initialization works before initialization in constructor, in the same order as variable defined in code.
Has Java always behaved like this?
Yes.
In that case (I personally consider this a little bit confusing): Is it likely to be removed in future Java versions?
No, Java is backward compatible language, this is basic and will not be changed.
Would you try to avoid it?
If you want in-place initialization, make sure that it's independent of initializing of other variables. Otherwise initialize it in the constructor. Don't make complex in-place initialization.
Upvotes: 1