All programmers all over the world will be committed 2004 - 05 - 15Missair Click: 49
Release date wrong all the world will mistake the programmer programmers all over the world are guilty of: 2003--12--29 Author: Tsai Yung
At that year, the international superstar Jackie Chan's "Dragon" exposure, everyone accused him to face the wife Lin Fengjiao, forced him to come to hold a reporter meeting, to the world, he made "all men who will commit" all men in the world ". I have never committed this mistake, and I often think that I am not a man.
Although I didn't commit "all men who made people in the world", I have committed the "mistakes" all the programs all over the world. " Regardless of the language of use, all programmers around the world must have made this mistake, that is: too dependent on the compiler, but I don't know what the compiler did.
In general, the higher-level programming language will provide more grammar to facilitate the program, which is commonly known as syntactic sugar, I call it "Sweets on the grammat". Although it is sweet, if you have failed to understand the essence of the syntax, it is likely that there is no sweetener, but it is suffering. Not long ago, I received an email, the reader lists the Java programs below, saving me. After reading this program, I am sure this is a "all the mistakes all of the world" will be made. " // Program 1
Class Singleton {Private Static Singleton Obj = New Singleton (); Public Static Int Counter1; Public Static Int Counter2 = 0; Private Singleton () {Counter1 ; Counter2 ;}
Public static singleton getinstance () {return obj;}
}
// Program 2public class mymain {public static void main (string [] args) {singleton obj = singleton.getinstance (); system.out.println ("obj.counter1 ==" Obj.counter1); system.out. Println ("Obj.counter2 ==" Obj.counter2);}}
The result is: obj.counter1 == 1 obj.counter2 == 0
Have you been scared by this result? At first glance, you are likely to think that the value of Counter1 and Counter2 will be equal, but the implementation results are obviously not the case. In fact, the program 1 is compiled by the program should be equivalent to the following programs 3: // Program 3class singleton {private static singleleton obj; public static int counter1; public static int counter2; static {
// This is Class Constructor // Before entering this class constructor, Class has been configured by JVM //, all Static Field will be set to 0 first, // So at this time, COUNTER1 and Counter2 are already 0, Singleton is null obj = new singleleton (); // The problem is generated by this line program to generate // counter1 will not be set to 0 counter2 = 0; // counter2 is set again 0 (actually more) } private singleton () {
// This is Instance Constructionor Counter1 ; Counter2 ;
Public static singleton getinstance () {return obj;}
}
This is because: When the Class has Static Field, the compiler will automatically move these narratives in the Class Constructor when the value is set directly through "= ...". Similarly, when the Class has an Instance Field, the compiler will automatically move these narratives in the instance constructor while setting the value in the declaration of "= ...".
This program has not initialized Static Field in Class Constructor (this time, counter1 and counter2 are 0), call Instance Constructor, and instance constructor will also go to the value of Static Field, make Counter1 and Counter2 Getting 1. Then Instance Constructor is executed, go back to the Class Constructor, then set the value of counter2 to 0 (but counter1 remains unchanged). The last result: Counter1 is equal to 1, and counter2 is equal to 0.
To correct the procedure 1, the method has three:
- Method 1: Turn the declaration of Singleton Field to Counter1 and Counter2 Field. This is the best practice.
- Method 2: During the declaration of Counter2 = 0, the "= 0" part is deleted. This method is only in hope
- Method 3: Move the initialization action to the Class Constructors, write itself without relying on the compiler. This is the most insurance.
How to avoid committing a mistake of all the issues of all the world will make a big man, I have given the Java programmers' suggestions:
- Reading Java Language Specification
- When there is a question, use JAVAP provided by J2SDK to reverse the translation of Java Bytecode, directly observe the resulting results.
Below is the demonstration of I use Javap to reverse group translation programs:
C: /> javap - c - classpath.singleton
Compiled from mymain.java class singleton extends java.lang.object {public static int counter1; public static int counter2; public static singleleton getInstance ();
Static {};
Method Singleton () 0aload_0 1invokespecial # 1
Method static {} 0New # 5
In fact, Java's syntactic sugar is not much, C # Syntactic Sugar is really omnipotent, and therefore, C # beginners are easier to commit "all programmers all over the world will make mistakes". Many C # books will introduce the C # syntax, while describing the results of MSIL (.NET intermediate language, similar java's Bytecode), Java's book is so fresh.
Although it is "all the mistakes all of the world will make a mistake", but this does not mean that you have made this mistake, you can still "look up at Cao Qitai with love to borrow money." As long as you have an heart, this is still avoidable.
I have a little added instructions:
From today, it should be understood that the concept of constructors is in two levels: one is a class constructor, one is the instance constructor class constructor assigns a value of Static's variables. Example constructor is specifically assigned to non-Static variables containing instance constructors, for class variables and instance variables, there are two modifications (four variables have four variables), respectively, as follows: public static int INT i; public static int i = 0; public INT i; public int i = 0; the difference between direct initialization and non-direct initialization. Direct initialization and non-direct initialization declarations are different, the difference is as follows: Direct initialization is actually written together with the statement and assignment, in fact, it is below: public static int i; static {i = 0;} and public INT i; {i = 0;} and static {} and {} are actually the effect of a class constructor or instance constructor.
So, the above class is actually as follows:
Class singleton {private static singleleton obj; static {obj = new singleleton ();
Public static int counter2; static {counter2 = 0;} private singleton () {counter1 ; counter2 ;}
Public static singleton getinstance () {return obj;}
}
In the above code, the three variables of OBJ, Counter1, actually given the memory address simultaneously, that is, the initial assignment of the memory (ie, the pointer, this can be debug with the class with JB. When you see), then, the program is running to static {Obj = new singleleton ();} code block, and then calls the instance constructor, that is, the example constructor is included in the "class constructor" above, after the call is finished , Counter1 and Counter2 are assigned 1, in turn, the program is running to static {counter2 = 0;} This will assign the counter2 to 0
The above description of the relationship between the class constructor and the instance constructor is described, and the STATIC variable and the STIC block are in fact, non-Static variables and non-Static blocks also have similar relationships and sequences, as long as they are created while the declaration, the effect They are all initialized in the constructor.