Obj. counter1 = 1
Obj. counter2 = 0
Have you ever been shocked by this result? At first glance, you may think that the values of counter1 and counter2 are equal, but the execution results are obviously not the same. In fact, the program after program 1 is compiled should be equivalent to program 3 below:
Class Singleton
{
Private static Singleton obj;
Public static int counter1;
Public static int counter2;
Static
{
// This is the class constructor.
// Before entering this class constructor, the class has been
// Configure the memory. All static fields are set to 0 first,
// Therefore, counter1 and counter2 are both 0,
Singleton is null.
Obj = new Singleton ();
// The problem is caused by this program.
// Counter1 will not be set to 0 here
Counter2 = 0;
// Counter2 is set to 0 again (in fact, this is an extra action)
}
Private Singleton ()
{
// This is instance constructor
Counter1 ++;
Counter2 ++;
}
Public static Singleton getInstance ()
{
Return obj;
}
This is because when the class has a static field and its value is directly set at the Declaration through the "=..." method, the compiler will automatically move these statements to the class constructor in sequence. Similarly, when the class has an instance field and its value is directly set at the Declaration through the "=..." method, the compiler will automatically move these statements to the instance constructor in sequence.
In class constructor, this program calls instance constructor before initializing static field (at this time, both counter1 and counter2 are 0, the instance constructor will change the value of the static field so that both counter1 and counter2 become 1.
After instance constructor is executed, return to class constructor and set counter2 to 0 (but counter1 remains unchanged ). The final result is: counter1 equals 1, and counter2 equals 0.
To correct procedure 1, there are three methods:
Method 1: Adjust the declaration of singleton field to counter1 and counter2 fields.
This is the best practice.
Method 2: delete the "= 0" part of the counter2 = 0 announcement. This approach is only expected.
Method 3: Move the initialization action to the class constructors and write it by yourself without relying on the compiler. This is the safest practice.
How to avoid making mistakes that all programmers in the world will make? My suggestions for Java programmers are as follows:
-Familiar with Java Language Specification
-If you have any questions, use the javap provided by J2SDK to reverse group the Java Bytecode and directly observe the compiled result.