Code reuse is one of the many notable functions of Java. This chapter describes two methods to achieve this goal:
Combination: you only need to generate existing class objects in the new class.
Inheritance: Creates a new class based on the type of the existing class. You do not need to change the form of the existing class. This is the form of the existing class and add new code to it.
7.1 combined syntax
If you want to initialize object reference in the class, you can perform the following operations in the Code:
1. Define the object. This means that they can always be initialized before the constructor is called.
2. In the constructor of the class.
3. Before using these objects, this method becomes inert initialization.
4. Use instance initialization.
7.2 inheritance syntax
When an export class object is created, the object contains a sub-object of the base class. This sub-object is the same as the object directly created using the base class. The difference is that the latter comes from the outside, and the sub-objects of the base class are encapsulated inside the objects of the export class.
Correct initialization of base class sub-objects is crucial, and there is only one way to ensure this: In the constructor, the constructor calls the constructor to execute initialization, the constructor has all the knowledge and capabilities required to perform base class initialization. Java automatically inserts a call to the default constructor of the base class in the constructor of the export class.
However, if there is no default constructor, or you want to call a base class constructor with parameters, you must use the keyword "super" to compile the statements of the base class constructor, in addition, it is configured with an appropriate parameter list. Also, calling the accumulate constructor is the first thing you need to do in the export class constructor.
7.3 proxy
The third relationship becomes a proxy, and Java does not provide direct support. This is the middle way between inheritance and combination, because we place a member object in the class to be constructed (like combination ), but at the same time, we expose all the methods (like integration) of the object member in the new class ).
An example is as follows:
//: reusing/SpaceShip.javapublic class SpaceShip extends SpaceShipControls { private String name; public SpaceShip(String name) { this.name = name; } public String toString() { return name; } public static void main(String[] args) { SpaceShip protector = new SpaceShip("NSEA Protector"); protector.forward(100); }} ///:~
//: reusing/SpaceShipDelegation.javapublic class SpaceShipDelegation { private String name; private SpaceShipControls controls = new SpaceShipControls(); public SpaceShipDelegation(String name) { this.name = name; } // Delegated methods: public void back(int velocity) { controls.back(velocity); } public void down(int velocity) { controls.down(velocity); } public void forward(int velocity) { controls.forward(velocity); } public void left(int velocity) { controls.left(velocity); } public void right(int velocity) { controls.right(velocity); } public void turboBoost() { controls.turboBoost(); } public void up(int velocity) { controls.up(velocity); } public static void main(String[] args) { SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector"); protector.forward(100); }} ///:~
7.4 combination and integration
Although the compiler forces you to initialize the base class and requires you to do so at the beginning of the constructor, it does not supervise you and must initialize the member object as well, therefore, you must always pay attention to this point.
Sometimes you need to execute some necessary cleaning activities within the lifecycle of the class. This can be used to learn the C ++ destructor. we add a dispose method to each inherited object. Pay attention to the call sequence of the basic class cleanup method and member object cleanup method, to prevent a sub-object from being dependent on another sub-object. Generally, the form used should be the same as that applied by the C ++ compiler on its destructor: First, it executes all specific cleanup actions of the class, the order is the opposite of the generated order (usually this requires that the base class elements remain alive); then, as we demonstrated, the cleanup method of the base class is called.
In many cases, cleaning is not a problem. You only need to let the Garbage Collector complete this action. However, once garbage collection is involved, there will be little to trust, because the Garbage Collector may recycle objects in any order it wants. The best way is not to rely on the garbage collector to do anything except the memory. If you need to clean up, it is best to write your own cleanup method instead of using finalize.
If the Java base class has the name of a method that has been overloaded, the method names that are redefined in the export class do not mask any version of the method in the base class (this is different from C ++ ).
The override annotation is added to Java se5, which prevents unexpected overloading when you do not want to overload it.
7.5 select between combination and inheritance
Whether to use combination or inheritance, the clearest judgment method is to ask whether you need to transform from a new class to a base class.
7.6 protected keywords
The protected keyword indicates that a class user is private, but for any export class that inherits from this class or any other class in the same package, it is accessible.
7.7 upward Transformation
This term is used for historical reasons, and is based on the traditional method of drawing the class inheritance graph: the root is the top of the page, and then gradually goes down.
7.8 final keywords
Three scenarios used by final: data, methods, and classes.
7.8.1 final data
If it is a basic data type, final keeps the value constant;
If it is an object reference, final makes the reference constant.
A static and final domain only occupies a storage space that cannot be changed. When static is defined, only one copy is emphasized. If final is defined, it is a constant.
The final domain must be assigned a value at the domain definition or each constructor using an expression, which is exactly why the final domain is always initialized before use.
Java allows the parameter to be declared as final in the parameter list. This means that you cannot change the object to which the parameter points in the method.
7.8.2 final Method
There are two reasons for using the final method. First, lock the method to prevent any integration class from modifying its definition. The second cause is inefficiency. This early Java version policy is somewhat similar to the inline keyword in C ++.
All private methods in the class are implicitly specified as final. Because the privagte method cannot be used, it cannot be overwritten. You can add final modifiers to the private method, but this does not add any additional meaning to the method.
7.8.3 final class
When a class is defined as final, it means that you do not intend to inherit the class and do not allow others to do so.
7.9 initialization and class loading
It can be said that "the class code is loaded only when it is used for the first time", which usually refers to loading the first object of the class, but when accessing the static domain or static method, load will also occur.
When a class runs Java, the first thing that happens is to try to access the main method of the class (a static method), so the loader starts and finds the compilation code of the class. During its loading process, the compiler notices that it is a base class (known by the keyword extends), so it continues to load. Whether or not you want to generate an object of the base class, this will happen.
If the base class has its own base class, the second base class will be loaded, and so on. Next, the static initialization in the base class will be executed, followed by the next export class, and so on. This method is very important because the static initialization of the export class may depend on whether the base class member can be correctly initialized.
Next, the memory is cleared, all basic types are set to default values, and object references are set to null. Then, the constructor of the base class is called. The constructor of the base class is the same as the constructor of the export class and goes through the same process in the same order. After the constructor of the base class is complete, the instance variables are initialized in its order. Other parts of the constructor are executed.