Java instantiation of an abstract class object method tutorial
preface
Recently, in the process of learning, I found a problem. An abstract class cannot build the object through new without implementing all the abstract methods, but the abstract methods can have their own construction methods. This confused me. Since there are construction methods and can't be created through new, can abstract classes be instantiated before they become concrete classes?
Abstract classes cannot be instantiated directly in Java. But often this feature of abstract classes becomes a troublesome obstacle. For example, if I want to use dynamic proxy to give an abstract class the ability to execute abstract methods, there will be two difficulties: 1 A dynamic proxy can only create a proxy object that implements an interface, not an object that inherits an abstract class. For this purpose, there are some implementations in the standard JVM, such as javassist, which can use the bytecode tool (proxyfactory).
In Android, if you want to construct an abstract class object, I'm afraid it can only be constructed after new classname() {} or inheritance. However, these two methods cannot be operated directly by their class objects, which leads to some problems that can not reach the abstract ability we need.
Here is a detailed description of the scenario described in the first paragraph:
First, an interface file is defined as follows (friends familiar with Android can see that this is an API configuration interface for retro to generate proxy objects):
Secondly, write an abstract class to implement only one method of the interface (used to simulate interface data):
Then we need a tool, such as mockmanager, to combine our existing realapi objects and mockapi classes to construct a hybrid object. When the method defined in mockapi is executed, the object is executed directly. When the method is not defined in mockapi, it calls the realapi method. The calling method is as follows:
Through javassist, it is easy to complete the above functions. Create a proxyfactory object, set its superclass to mockapi, then filter the abstract methods, and set the method handler to call the same parameter method of the realapi object. The code implementation will not be given here.
But on Android, this method of javassist will throw
Similar exceptions. The reason is probably that the implementation of virtual machines on Android is slightly different from the standard, so here we turn to annotation processor, another direction of dynamic code generation.
If the annotation processor is used for implementation, the idea is much simpler, but the process is still somewhat tortuous:
First, define an annotation to mark the abstract class of the object to be constructed
Processor obtains the element object of the class according to the annotation, which is a class like object. Because class does not exist in the precompile phase, use class Forname cannot obtain the class object required by the runtime, but element provides methods similar to class reflection, as well as typeelement and executableelement. What are the abstract methods of using the element object to analyze the abstract class of annotations, Generate an implementation class that inherits this class (non Abstract) and implement all abstract methods in this class. Because these abstract methods will not be actually used, it only needs to be compiled. My choice is that each method body throws an exception to prompt that the method is an abstract method and cannot be called directly. Some tools can be used to simplify the work of the method generating code, such as autoprocessor and For the specific implementation of javapool, refer to the project code at the end of the article. The generated code is roughly like this:
The implementation class is obtained by de reflection according to the class name of the abstract class, and then an implementation object is constructed by calling its construction method according to the reflection.
Construct a dynamic proxy, the real object passed into realapi and the implementation object of the abstract class constructed in the previous step. Judge which object represents its method behavior according to the definition in the abstract class: if there is a definition in the abstract class, that is, the method is not an abstract method, the implementation object of the extraction class will execute; Instead, it is executed by the real object of the interface.
After completing the above work, you can use the build method to construct a proxy object mixed with real interface and abstract class methods as mentioned at the beginning. Although the called class is hard coded in essence, it is automatically generated by the annotation processor without manual maintenance. It is basically the same as using javassist.
I have implemented a tool for simulating retrofit requests using the method in this article (there is a link at the end of the article), but it can be used to realize many requirements that need to construct abstract classes, and more usage scenarios need to be mined.
The source code implementation mentioned in this article can be found in the project retrofit mock result or local download;