Read Catalogue
- Recommendation 36: Use construction code block refiners
- Recommendation 37: Building blocks of code you think about it.
- Recommendation 38: Use static internal classes to improve encapsulation
- Recommendation 39: Use the constructor of an anonymous class
- Recommendation 40: The constructors of anonymous classes are very special
Recommendation 36: Use construction code block refiners
What is called a code block? Using curly braces to encapsulate multiple lines of code together to form a separate data body, the code set that implements a particular algorithm is a block of code, in general the code can not run alone, it must have a running body. There are four types of code blocks in Java:
- Ordinary code block: is the code fragment that is enclosed in "{}" after the method, it cannot run alone and must be executed by means of the method name;
- Static code blocks: use static modifiers in a class, and code snippets enclosed in "{}" for static variable initialization or environment initialization before object creation.
- Synchronizing code blocks: Using the Synchronized keyword adornment, and using a code fragment enclosed in "{}", which indicates that only one thread can enter the method block at a time, is a multithreaded protection mechanism.
- Constructing code blocks: There are no prefixes and suffixes in the class, and code fragments enclosed in "{}" are used;
I know that there is at least one constructor in a class (if not, the compiler selflessly creates an parameterless constructor for it), and the constructor is called when the object is generated, which is now for you: what is the relationship between the constructor and the code block and when is the code block executed? Before answering this question, let's look at how the compiler handles building blocks of code, as shown in the following code:
1 public class Client36 {2 3 {4 //Construction code block 5 System.out.println ("Execute Construction code block"); 6 } 7 8 public Cl Ient36 () {9 System.out.println ("Execute non-parametric construction"), }11 public Client36 (String name) { System.out.println ("Executed with a reference structure"); }15}
This is a very simple code, it contains constructs the code block, the parameterless constructs, has the parameter constructs, we know that the code block does not have the independent execution ability, then how the compiler handles constructs the code block? Very simply, the compiler inserts the construction code block into the front of each constructor, which is equivalent to the following code:
1 public class Client36 {2 3 public Client36 () {4 System.out.println ("Execute Construction code block"); 5 System.out.println ("Execute non-parametric construction"); 6 } 7 8 public Client36 (String name) {9 System.out.println ("Execution Construction code block"); System.out.println (" To perform a structure "); }12}
The most front-end of each constructor is inserted into the construction code block, and it is clear that constructing a block of code before generating an instance from the New keyword and then executing other code, that is to say, constructs a block of code that executes first within each constructor (note that the construction code block is not run before the constructor, It depends on the execution of the constructor, and with this in mind, we can apply the construction code block to the following scenario:
- Initialize instance variables (Instance Variable): If each constructor initializes a variable, it can be implemented by constructing a block of code. Of course, you can do this by defining a method, and then invoking the method in each constructor, yes, it can be resolved, but to call the method in each constructor, and this is its disadvantage, if the way to construct blocks of code is not defined and called, it will be written directly by the compiler to each constructor, This is a great way to solve this problem.
- Initialize the instance environment: an object must be present in the appropriate scenario, and if there is no appropriate scene, you will need to create the sub-scene when creating the object, for example, in JEE development, to generate an HTTP request must first establish an HTTP Session, in creating an HTTP The request can be constructed by constructing a block of code to check if the HTTP session already exists and does not exist.
The above two scenarios take advantage of the two features that construct blocks of code: run in each constructor and run first in the constructor. A good use of this feature of building blocks of code can not only reduce the amount of code, but also make the program easier to read, especially when all the constructors are to implement the logic, and this part of the logic is very complex, then you can write a number of construction code blocks to implement. Each block of code accomplishes different business logic (of course, the constructor is as simple as possible, which is the basic principle), and is stored in business order, so that the JVM executes sequentially in order to create the modular creation of complex objects as the instance object is created.
Back to top recommendation 37: Building blocks of code you think about it.
In the previous recommendation, we proposed to use building blocks of code to simplify the code, and also learned that the compiler would automatically insert the construction code block into each constructor, so let's see if the compiler is smart enough to solve the real development problem for us, and there is a case that counts the number of instance variables for a class. You have to say, this is very simple, in each constructor to add an object counter to remedy the problem? Or we can use the previous recommendation to construct blocks of code, which is true, so let's see if the following code works:
1 public class Client37 {2 public static void Main (string[] args) {3 new Student (); 4 New Student ("Zhang San"); 5
new Student (10); 6 System.out.println ("Number of instance objects:" +student.getnumofobjects ()); 7 } 8} 9 class Student {One //Object counter private static int numofobjects = 0;13 +/ /Construction code block, calculation of the number of objects produced numofobjects++;17 }18 Public Student () { }22 //have a parametric construct call without a parameter construct of public Student (String stuname) {( ); Student//The parameter structure does not call the parameterless construct , public (int stuage) { }32 //Returns how many instance objects are created in a JVM. static int getnumofobjects () { return numofobjects;35 }36}
Does this piece of code work? Can you calculate the number of instance objects? If the compiler inserts a construction code block into each constructor, the constructor with the string parameter may have a problem, it calls the parameterless construct, and the student object generated by it executes two blocks of construction code: one is to construct a block of code without a parameter constructor call, One is to execute its own block of construction code, so that the calculation is not accurate, the main function actually produces 3 objects in memory, but the result is indeed 4. But is that really the case? After we run, the result is:
Number of instance objects: 3;
The number of instance objects is still 3, the program is no problem, strange? Not surprisingly, the previous suggestion was that the compiler would insert the construction code block into each constructor, but there is one exception: if you encounter the This keyword (that is, when the constructor calls its own other constructors), then the construction code block is not inserted, for our example, The compiler, at compile time, discovers that a string parameter constructor calls the parameterless construct, and then discards the insert Construction code block, so that only one construction code block is executed.
Why is the Java compiler so smart? This also from the birth of the construction code block, the construction code block is to extract the common amount of constructors, reduce the code generated by each constructor, so Java is very smart to think of inserting code into the constructor of this method, and call other constructors are not inserted, Make sure that each constructor executes only one construction code block at a time.
Also need to explain, we must not think this is a special case, that super will be similar to the processing, in fact, in the construction block processing, the super method does not have any special place, the compiler only the construction code block inserted into the super method after the execution. This is the only difference.
Note: Use building blocks of code with ease, and Java is already thinking about what you think.
Back to top recommendation 38: Improve encapsulation with static internal classes
There are two types of nested classes (Nested Class) in Java: Static inner classes (also called static nested classes, statically Nested Class), and inner classes (Inner Class). This time the main look at static inner class. What is a static inner class? is an inner class, and static (static) is a static inner class that can put the static modifier in front of the class only if it is a static inner class, and at any other time the static is not decorated with the class.
The form of static inner classes is well understood, but why do you need static inner classes? That's because the static inner class has two advantages: it enhances the encapsulation of the class and improves the readability of the code, and we use the following code to explain these two advantages.
1 public class Person {2 //Name 3 private String name; 4 //Family 5 private home home; 6 7 public Per Son (String _name) {8 name = _name; 9 }10 /* Home, name setter and getter method slightly */12 public static class H ome {+/ /home Address + private string address;16 //Home phone + private string tel;18 public Home ( String _address, String _tel) { address = _address;21 Tel = _tel;22 }23 /* address, Tel's setter and getter method slightly */24 }25}
Among them, the person class defines a static internal class home, which means "People's family information", because the home class encapsulates the family information, no longer in person to define the attributes such as Homeaddr,hometel, which makes the encapsulation of the improved. At the same time, we can only use the code to analyze the relationship between person and home, that is to say, semantic enhancement, readability improved. So it's very clear what it means when it's used.
public static void Main (string[] args) { //define Zhang San this person p = new Man ("Zhang San"); Set Zhang San family information p.sethome ("Beijing", "010"); }
Define Zhang San this person and then set Zhang San family information through the Person.home class, is that just the same as we are in the world? First register the person's primary information, and then register the people's classification information. Perhaps you have to ask, this and we generally define the class God is different? What attractive place is there? As shown below:
- Improved encapsulation: From the location of the code, the static inner class is placed inside the outer class, and its code layer meaning is that the static inner class is the sub-behavior or sub-property of the outer class, and there is a certain relationship between the two, for example, in our case, see the home class to know that it is the person's home information.
- Improve the readability of your code: The associated code is put together and readability is definitely improved.
- In the shape of the interior, the external: static inner class, although it exists in the outer class, and the compiled class file also contains the external class (the format is: External class +$+ inner class), but it can be separated from the external class exists, it is said that we can still declare a home object through new home, just need to import " Person.home "only.
Explaining so much, you may feel that the outer class and the static inner class is a combinatorial relationship (composition), which is wrong, the external class and the static inner class has a strong association between, this is only reflected in the "literal", while the deep-seated abstract meaning is based on the design of the class.
What is the difference between a static class inner class and an ordinary inner class? Here's a description:
- Static inner classes do not hold references to external classes: in ordinary inner classes, we can directly access the properties and methods of the outer class, even if the private type is accessible, because the inner class holds a reference to an external class and is free to access. Static internal classes, however, can access only static and static properties of external classes (which are determined by their code location if private permissions are available), while others are inaccessible.
- Static inner classes do not depend on external classes: the ordinary inner class is interdependent with the outer class, and the inner class instance cannot be detached from the external class instance, that is, they will die together, declare together, be garbage collected, and static inner classes can exist independently, even if the outer class dies, the static inner class can exist.
- Ordinary inner classes cannot declare static methods and variables: Ordinary inner Classes cannot declare static methods and variables, note that variables are said here, constants (that is, properties of final static modifiers) are still possible, while static inner classes resemble external classes without any restrictions.
Back to top recommendation 39: Using the constructor of an anonymous class
Read the following code to see if you can compile:
public static void Main (string[] args) { List list1=new ArrayList (); List list2=new ArrayList () {}; List list3=new ArrayList () {{}}; System.out.println (list1.getclass () = = List2.getclass ()); System.out.println (list2.getclass () = = List3.getclass ()); System.out.println (list1.getclass () = = List3.getclass ()); }
Note ArrayList behind the point: List1 variable behind nothing, list2 behind a pair of {},list3 behind there are two nested {}, this program can compile it? If you can compile, what is the result of the loss?
The answer is to compile, and the output is 3 false. List1 is easy to understand, is the life of the ArrayList instance object, that List2 and LIST3 representative of what is it?
(1), List2 = new ArrayList () {}:LIST2 represents the Declaration and assignment of an anonymous class, which defines an anonymous class that inherits from the ArrayList, except that there is no way to overwrite it, whose code resembles the following:
Defines an internal class that inherits ArrayList classes class Sub extends ArrayList { } //Declaration and Assignment List list2 = new Sub ();
(2), list3 = new ArrayList () {{}}: This statement is a bit strange, with two pairs of {}, we can understand separately, this is also an anonymous class definition, its code is similar to:
Defines an internal class that inherits ArrayList classes class Sub extends ArrayList { { //Initialize code block } } //Declaration and assignment List List3 = new Sub ();
See, just a bit more initialization block, the function of the constructor, we know that a class must have a constructor, and the constructor name and class name is the same, the question is: what is the constructor of the anonymous class? It doesn't have a name! Obviously, the initialization block is its constructor. Of course, a constructor block in a class can be multiple, which means that the following code appears:
List list4 = new ArrayList () {{} {} {} {} {}};
The above code is correct, there is no problem, now clear, anonymous class although there is no name, but also can have a constructor, it uses a constructor block instead of the constructor, the above 3 output is very obvious: although the parent class is the same, but the class is different.
Back to top tip 40: Anonymous class constructors are very special.
In the previous recommendation, we talked about anonymous classes that have no names, but can have an initialization block to act as constructors, so is this constructor completely different from a normal constructor? Let's look at an example, design a calculator, add and subtract, the code is as follows:
1 public class Calculator {2 enum Ops {3 ADD, SUB 4 }; 5 6 private int I, j, result; 7 8 // Non-parametric construction 9 public Calculator () {Ten }12 //With a parametric structure of public Calculator (int _i, int _j) { i = _i;16 j = _j;17 } +/ /set symbol, is addition or subtraction operation protected void Setoperator (Ops _ops) { + result = _ops.equals (ops.add)? i + J : i-j;22 }23 //Get operation result of public int GetResult () { }28 return result;27 29}
The intent of the code is to pass a number of two int types through the constructor, and then write a client call based on the operator (addition or subtraction) of the set:
public static void Main (string[] args) { Calculator C1 = new Calculator (1, 2) { { setoperator (ops.add); } }; System.out.println (C1.getresult ()); }
This anonymous class code is very clear: receive two parameters 1 and 2, and then set an operation symbol, calculate its value, the result is 3, which is no doubt, but there is a problem in the middle: the anonymous class declaration with the parameter is called when the constructor? Let's simulate this procedure:
Addition calculation Class Add extends calculator{ { setoperator (ops.add); } Overwrite the constructor of the parent class public Add (int _i, int _j) { }}
is the anonymous class equivalent to this add class? Some people may say: The above just add a name to the anonymous class, the others are not changed, it must be equivalent, no doubt, well, write a client call the Add class method to see. The code is just a little bit, because it's simple new ADD, then call the parent class's GetResult method, and after testing, the output is 0 (why instead of 0?) This is easy, there is no assignment for the structure of the argument). This means that the two are not equivalent, but why?
Because of the special processing mechanism of the constructors of anonymous classes, all constructors of the generic class (that is, a class that does not display the name) are called the parameterless constructor of the parent class by default, and the anonymous class has no name and can only be replaced by building blocks of code, and there is no argument or parameterless constructor. It invokes the same argument constructor of the parent class directly at initialization, and then calls its own construction code block, which means that the anonymous class above is equivalent to the following code:
Addition calculation Class Add extends calculator{ { setoperator (ops.add); } Override the constructor method for the parent class public Add (int _i, int _j) { super (_i,_j); }}
It will first call the parent class with two parameters of the constructor, rather than the parameterless construct, which is the difference between the constructor of the anonymous class and the ordinary class, but this is really a few people carefully pondering, because its processing mechanism conforms to the habit, I pass two parameters, I want to call the parent class has two parameters of the construction, And then execute my own constructor, and the Java processing mechanism is exactly how it is handled.
Ahvari Source: http://www.cnblogs.com/selene/This article to study, research and sharing of the main, copyright belongs to the author and the blog Garden, Welcome to reprint, if the text is inappropriate or wrong place also hope the great god you hesitate to point out. If you feel that this article is helpful to you than "recommend" it! If you have better suggestions, we should discuss together with the message, and make progress together! Thank you again for your patience in reading this post.
Reprint-Write high-quality code: 151 Suggestions for improving Java programs (3rd: Classes, objects and methods ___ recommended 36~40)