V. Initialization and cleanup
1. Use the constructor to ensure initialization
In Java, by providing a constructor, the designer of the class ensures that each object is initialized. When creating an object, if its class has a constructor, Java will automatically invoke the appropriate constructor before the user has the ability to manipulate the object, guaranteeing initialization. The name of the constructor is the same as the name of the class. (The coding style for the first lowercase of each method does not apply to the constructor)
Constructors help reduce errors and make your code easier to read. Conceptually, "Initialize" and "create" are each other and independent. In Java, "Initialize" and "create" are bundled together, and they cannot be separated.
A constructor is a special type of method because it has no return value. This is significantly different from the null (void) return value. The constructor does not return anything (the new expression does return a reference to the new object, but the constructor itself does not have any return values).
2. Method overloading
In Java, constructors are a reason for forcing overloaded method names. Since the name of the constructor is already determined by the class name, there can be only one constructor name. So what if you want to create an object in a variety of ways? Suppose you want to create a class that can be initialized in a standard way, or you can read information from a file. This requires two constructors: a default constructor, and another takes a string as a formal parameter--the string that represents the file name required to initialize the object. Because they are constructors, they must have the same name, that is, the class name. A method overload must be used for constructors that have the same method name and have different form parameters.
① Distinguishing Overloaded methods
Each overloaded method must have a unique list of parameter types. Even the difference in the order of the parameters is sufficient to distinguish two methods. However, it is not recommended to do so.
② involves basic types of overloads
The basic type can be automatically promoted from a "smaller" type to a "large" type, which, once involved in overloading, can cause some confusion.
The constant value is treated as an int value.
If the data type passed in (the actual data type) is less than the formal parameter type declared in the method, the data type is promoted. The char type is slightly different, and if you cannot find a method that exactly accepts the char parameter, the char is promoted directly to the int type.
If the actual argument passed in is greater than the formal parameter of the overloaded method declaration, the narrowing conversion is performed through the type conversion. If you do not do this, the compiler will make an error.
③ to differentiate overloaded methods with return values
When you differentiate overloaded methods, why should we only use the class name and the parameter list of the method as standard? Can you use the return value of the method to differentiate it?
The answer is no .
Because sometimes we don't care about the return value of the method, we want the other effect of the method call, and then we call the method and ignore the return value. For example, this method is called: F ();
3. Default constructor
The default constructor (aka "parameterless" constructor) is a non-formal parameter--its role is to create a "default object". If you write a class that does not have a constructor, the compiler will automatically create a default constructor for you. However, if you have already defined a constructor (with or without parameters), the compiler does not automatically create a default constructor.
4.this keywords
If there are two objects of the same type, they are A and B, respectively. You might want to know how to get both objects to call the same method:
Class Banana {void peel (int i) {/*.....*/}}public class Bananapeel {public static void Main (string[] args) { B Anana a = new Banana (), B = new Banana (); A.peel (1); B.peel (2);} }
If there is only one Peel method, how does it know if it is called by a or is it called by B?
In order to be able to write code with simple, object-oriented syntax-that is, "Send messages to Objects"-the compiler does some behind the scenes work. It secretly passes the reference of the object being manipulated as the first parameter to Peel (). So the invocation of these two methods becomes this:
Banana.peel (a,1);
Banana.peel (b,2);
This is the internal representation. We are not able to write code like this.
Suppose you want to get a reference to the current object inside the method. Since this reference was "secretly" passed by the compiler, no identifiers are available. However, there is a special keyword: this. The This keyword can only be used inside a method, representing a reference to the "object that called the method". The usage of this and other object references are not different. However, it is important to note that if you call another method within a method that uses one class, you do not have to use this to call directly.
Use this only where necessary.
① using constructors in constructors
It is possible to write multiple constructors for a class, and sometimes you might want to call another constructor in one constructor to avoid repeating the code. This keyword can be used to do this.
Usually when this is written, it means "this object" or "current object", and it itself represents a reference to the current object. In the constructor, if you add a parameter list to this, you have a different meaning. This results in an explicit call to a constructor that conforms to this parameter list. In addition, the constructor call must be placed at the very beginning, or the compiler will give an error.
The meaning of ②static
The static method is the method without this. A non-static method cannot be called inside the static method, which in turn is possible. (a static method can create its own reference, which, like the This effect, invokes a non-static method, such as the Main method.) And you can invoke the static method only through the class itself, without creating any objects.
5. Cleanup: End processing and garbage collection
Java has a garbage collector responsible for reclaiming memory resources that are occupied by useless objects. But there is also a special case: Suppose your object (not using new) obtains a "special" area of memory, because the garbage collector only knows to release the memory allocated through new, so it does not know how to release this "special" Memory of the object. Therefore, Java allows a method named Finalize () to be defined in the class. It works "hypothetically": once the garbage collector is ready to release the storage space occupied by the object, the Finalize () method is called first, and the memory occupied by the object is actually reclaimed when the next garbage collection action occurs.
There is a potential programming trap because some programmers (especially C + + programmers) may mistakenly consider Finalize () as a destructor in C + + (This function must be used for destroying objects in C + +). So it is necessary to make a clear distinction: in C + +, objects are bound to be destroyed, while Java objects are not always garbage collected. Or in other words:
1. Objects may not be garbage collected.
2. Garbage collection is not equal to "folding".
This means that if you have to perform certain actions before you no longer need an object, you have to do it yourself. Java does not provide a "destructor" or a similar concept, and to do similar cleanup, you must create a common way to perform cleanup work yourself. For example, suppose an object will draw itself to the screen during creation, and if it is not explicitly erased from the screen, it may never get cleaned up. If a erase function is added to Finalize () , when "garbage collection" occurs (not guaranteed to happen),finalize () gets the call and the image is erased. If "garbage collection" does not occur, the image will remain intact.
· You may find that the space the object occupies will not be freed as long as the program is not on the verge of storage space. If the program execution finishes and the garbage collector has not freed up any objects you create, the resources are all returned to the operating system as the program exits. This strategy is appropriate because garbage collection itself has a cost, and if you don't use it, you don't have to pay for that part of the cost.
What is the purpose of ①finalize ()
What is the real purpose of finalize () ?
This leads to the 3rd that needs to be remembered:
3. Garbage collection is only related to memory.
That is, the only reason to use the garbage collector is to reclaim memory that is not used by the program. Regardless of how the object is created, the garbage collector is responsible for releasing the memory that the object occupies. This limits the need for finalize () to a special case where the object is allocated storage space in a way other than creating an object. However, everything in Java is an object, and what about this particular situation?
The reason for finalize ()is that it is possible to use a similar C-language approach when allocating memory. This occurs primarily when using local methods, where the local method is a way to invoke non-Java code in Java. Local methods currently only support C and C + +, but they can invoke code in other languages, so you can actually invoke any code. In non-Java code, the malloc () function Family of C may be called to allocate storage space, and unless the free () function is called, storage space will not be freed, causing a memory leak. Of course, free() is a function in C and C + +, so it needs to be called in Finalize () with a local method.
②, you have to clean up.
To clean up an object, the user must call the method that performs the cleanup action at a time when it needs to be cleaned.
Java does not allow the creation of local objects, it must be created using new. Remember, neither garbage collection nor termination is guaranteed to happen. If the Java virtual machine does not face memory exhaustion, it will not waste time doing garbage collection.
③ Termination conditions
In general, you cannot expect finalize (), you must create additional "cleanup" methods, and explicitly call them. It seems thatfinalize () can only exist in obscure usages that programmers find difficult to use. However,finalize () has an interesting usage, and it does not rely on a call to Finalize () every time, which is the validation of the object termination condition .
When an object is no longer interesting-that is, it can be cleaned up, the object should be in a certain state so that the memory it occupies can be safely freed. For example, if an object represents an open file, the programmer should close the file before the object is recycled. As long as there are parts of the object that are not properly cleaned up, there is a very vague flaw in the program that Finalize () can be used to eventually discover the situation-although it is not always called. If a finalize () action causes the flaw to be found, then the problem can be identified-and that is what people really care about.
Here's a simple example:
classBook {boolean checkedout=false; Book (Boolean checkedout) { This. Checkedout =checkedout; } voidcheckIn () {checkedout=false; } protected voidFinalize () {if(checkedout) {System. out. println ("error:checked out"); //It is generally necessary to do this, assuming that the base class version of Finalize () also does something//because of the need for exception handling, this omission//super.fianlize (); }} Public classterminationcondition { Public Static voidMain (string[] args) {book novel=NewBook (true); Novel.checkin (); NewBook (true); SYSYTEM.GC (); }}
The end condition of this example is that all book objects should be checked in (check in) before being garbage collected. But in the main () method, a book was not checked in because of a programmer's error. Without Finalize () to verify the termination criteria, this flaw will be difficult to detect.
Note thatSystem.GC () is used to force the finalization action. Even if you do not, you can eventually find the wrong book object by executing the program repeatedly.
How the ④ garbage collector works
The speed at which Java allocates space from the heap can rival the speed with which other languages allocate space from the stack.
For example, you can think of the heap in C + + as a yard in which every object is responsible for managing its own territory. After some time, the object may be destroyed, but the site must be reused. In some Java virtual machines, the implementation of the heap is very different: it is more like a conveyor belt, and each new object is allocated, it moves forward one grid. This means that the allocation of object storage space is very fast. Java's "heap pointer" simply moves to an area that has not yet been allocated, and is more efficient than C + + allocating space on the stack.
In fact, the heap in Java may not work exactly like a conveyor belt. If that's the case, it's bound to lead to frequent memory paging-moving it out of the hard drive, so it looks like it needs more memory than it actually needs. Page scheduling can significantly affect performance, and eventually, after you have created enough objects, memory resources will be exhausted. The secret lies in the garbage collector's involvement. As it works, the space is reclaimed while the objects in the heap are compactly arranged so that the "heap pointer" can easily move closer to the beginning of the conveyor belt and avoid page faults as much as possible. By rearranging the objects in the garbage collector, a high-speed, infinite space-allocated heap model is implemented.
"Adaptive, generational, stop-copy, tag-sweep" garbage collector.
There are many additional techniques in the Java Virtual machine to increase speed. In particular, the technology associated with the loader operation, known as the "instant" compiler. This technology can translate all or part of the program to the machine code, the program speed is improved. When a class needs to be loaded (usually when the first object is created for the Class), the compiler finds it first . class file, and then mount the bytecode in memory. At this point, there are two options to choose from. One is to let the instant compiler compile all the code, and the other is that the immediate compiler compiles the code only when it is needed, known as lazy evaluation. Java hotspot Technology in the new JDK uses a similar approach, and the code performs some optimizations each time it executes, so the more times it executes, the faster it gets.
6. Initialization of Members
Java strives to ensure that all variables are properly initialized before being used. For local variables of a method, Java implements this assurance in the form of compile-time errors.
7. Constructor initialization
The constructor can be used for initialization. Keep in mind, however, that automatic initialization cannot be prevented, and it will occur before the constructor is called.
① Order of initialization
Within the class, the order in which the variables are defined determines the order in which they are initialized. Even if the variable definitions are scattered between the method definitions, they will still be initialized before any methods (including constructors) are called.
② initialization of static data
Static data consumes only one copy of the storage area, regardless of how many objects are created. The static keyword cannot be applied to local variables, so it can only be used for fields.
Static initialization occurs only when necessary. They are initialized only when the object is first created (or when static data is accessed for the first time). Thereafter, the static object is not initialized again.
The order of initialization is the first static object, and then the "non-Static" object.
Summarize the object creation process, assuming there is a class named Dog :
1. Even if the static keyword is not explicitly used, the constructor is actually a static method. Therefore, when you first create an object of type dog (the constructor can be considered a static method), or when the static method/static domain of the dog class is first accessed, the Java interpreter must look for the classpath to locate the Dog.class file.
2. Then load dog.class(This creates a class object), and all actions on static initialization will be performed. Therefore, static initialization is done only once when the Class object is first loaded.
3. When you create an object with new Dog () , you first allocate enough storage space on the heap for the Dog object.
4. This storage space is zeroed, which automatically sets all the basic type data in the Dog object to the default value, and the reference is set to NULL.
5. Perform all initialization actions that appear at the field definition.
6. Execute the constructor.
③ an explicit static initialization
Java allows multiple static initialization actions to be organized into a special "static clause" (sometimes called a "static Block"):
Public class fool { staticint i; Static { 666; }}
As with other static initialization actions, this code executes only once: When an object of this class is first generated, or when a static data member belonging to that class is first accessed (even if the object of that class has never been generated).
④ non-static instance initialization
Java also has a similar syntax called instance initialization, which is used to initialize non-static variables for each object.
It is identical to a static initialization clause, except that the static keyword is missing. This syntax is necessary to support the initialization of anonymous inner classes.
The instance initialization clause is executed before the constructor.
8. Array initialization
An array is just the same type of an object sequence or primitive type data sequence that is encapsulated together with an identifier name. Arrays are defined and used by the square brackets subscript operator [].
The compiler does not allow the size of the specified array. This brings us back to the question of "references". Now you have only one reference to the array (you have allocated enough storage space for the reference), and you have not allocated any space to the object itself. The initialization of an array can be performed with values enclosed by a pair of curly braces.
You can also initialize an array of objects with a list enclosed in curly braces.
① variable parameter list
The mutable parameter list behaves as follows:
void f (int ... a) {}
This is equivalent to having a int[] parameter. With a mutable argument list, you never have to explicitly write an array syntax, and when you specify a parameter, the compiler will actually populate the array for you. What you get is still an array.
Note: You should always use a mutable parameter list only on one version of the overloaded method, or not at all.
9. Enumeration type
The enum keyword was added to Java SE5, which makes it easy to handle when we need a group and use an enumeration type. The following is a simple example:
Public enum spiciness {Not , MILD, MEDIUM, hot, faming}
This creates an enumeration type named spiciness , which has 5 named values. Because instances of enumerated types are constants, they are denoted by the naming convention in uppercase letters.
In order to use an enum, you need to create a reference to that type and assign it to an instance:
Public class Simpleenumuse { publicstaticvoid main (string[] args) { = Spiciness.medium; Sysytem. out . println (Howhot); }} /* Outputmedium */
Enumeration types can use the ordinal () method, which represents the order of declarations for a particular enum constant, and the static value () method, which produces an array of these constant values in the order in which they are declared in the enum constant.
Although the enum appears to be a new type of data, this keyword generates some compiler behavior when the corresponding class is generated for the enum, so you can handle the enum as any other class to a large extent. In fact, an enum is a real-time class and has its own method.
An enum can be used within a switch statement.
10. Summary
Initialization occupies a critical low level in Java.
Learn the memory analysis of the deep understanding of the Java operating mechanism is very important, the summary of this article is still very incomplete, just take part, any heavy and way far ah!
Java Programming Ideas Learn Note 5