Problem:
Can I know the attributes and methods of a Java class at runtime? Can I call any of its methods?
The answer is yes. Java provides a reflection mechanism for implementation.
Directory
- What is the reflection mechanism of Java?
- Reflection API provided in JDK
- What functions does the Java reflection mechanism provide?
- Obtains the class object of a class.
- Obtain fields of A Class
- Obtain the method of the class
- Obtains the constructor of a class.
- Create a class instance
Class <t> function newinstance
Using the constructor object method newinstance
- Call a class function
Call private functions
- Set/obtain class attribute values
Private property
- Dynamically create proxy class
Dynamic proxy source code analysis
- Java reflection class <t> type source code analysis
- Java reflection principle analysis
Class file structure
JVM loads class objects and supports reflection
- Java reflection Application
1. What is the reflection mechanism of Java?
Java reflection is a key feature of Java as a dynamic (or quasi-dynamic) language. This mechanism allows the program to obtain the internal information of any class with a known name through reflection APIs at runtime, including its modifiers (such as public and static), superclass (such as object), implementation of interfaces (such as cloneable), also includes all information of fields and methods, and can change fields content or arouse methods at runtime.
The Java reflection mechanism allows programs to load, explore, and use classes that are completely unknown during compilation.
In other words, Java can load a class that is known only during runtime to obtain its complete structure.
Ii. reflection API provided by JDK
Java reflection-related APIs are included in the Java. Lang. Reflect package. The reflect package of JDK 1.6.0 is as follows:
Member Interface |
This interface can be used to obtain information about constructors of class members (fields or methods. |
Accessibleobject class |
This class is the basic class for field objects, method objects, and constructor objects. It provides the ability to mark reflected objects as canceling the default Java language access control check during use. |
Array class |
This class provides methods to dynamically generate and access Java arrays. |
Constructor class |
Provides information about the constructor of a class and the constructor interface of the class. |
Field Class |
Provides information about the domain of a class and the interface of the region class. |
Method class |
Provides information about a class method and interfaces of the class method. |
Modifier class |
Provides static methods and constants to decode class and member access modifiers. |
Proxy class |
Provides static methods to dynamically generate proxy classes and class instances. |
Iii. functions provided by the Java reflection mechanism
The Java reflection mechanism provides the following functions:
Determine the class to which any object belongs at runtime
Construct any class object at runtime
Judge the member variables and methods of any class at runtime
Call the method of any object at runtime
Create a class object at runtime
When using the Java reflection function, you must first obtain the Class Object of the class, and then obtain other objects through the class object.
Here we first define the classes used for testing:
class Type{public int pubIntField;public String pubStringField;private int prvIntField;public Type(){Log("Default Constructor");}Type(int arg1, String arg2){pubIntField = arg1;pubStringField = arg2;Log("Constructor with parameters");}public void setIntField(int val) {this.prvIntField = val;}public int getIntField() {return prvIntField;}private void Log(String msg){System.out.println("Type:" + msg);}}class ExtendType extends Type{public int pubIntExtendField;public String pubStringExtendField;private int prvIntExtendField;public ExtendType(){Log("Default Constructor");}ExtendType(int arg1, String arg2){pubIntExtendField = arg1;pubStringExtendField = arg2;Log("Constructor with parameters");}public void setIntExtendField(int field7) {this.prvIntExtendField = field7;}public int getIntExtendField() {return prvIntExtendField;}private void Log(String msg){System.out.println("ExtendType:" + msg);}}
1. Get the Class Object of the class
An instance of the class indicates the classes and interfaces in the running Java application. You can obtain class objects in multiple ways:
Call getclass |
Boolean var1 = true; Class <?> Classtype2 = var1.getclass (); System. Out. println (classtype2 ); Output: Class java. Lang. Boolean |
Use. Class syntax |
Class <?> Classtype4 = Boolean. Class; System. Out. println (classtype4 ); Output: Class java. Lang. Boolean |
Use static method class. forname () |
Class <?> Classtype5 = Class. forname ("Java. Lang. boolean "); System. Out. println (classtype5 ); Output: Class java. Lang. Boolean |
Use the type Syntax of primitive Wrapper Classes The returned native type is different from that returned by Boolean. Class. |
Class <?> Classtype3 = Boolean. type; System. Out. println (classtype3 ); Output: Boolean |
2. Obtain fields of the class
You can obtain an attribute of a class through the reflection mechanism, and then change the attribute value corresponding to an instance of the class. The Java class <t> class provides several methods to obtain class attributes.
Public field getfield (string name) |
Returns a Field object that reflects the specified public member fields of the class or interface represented by this class object. |
Public field [] getfields () |
Returns an array containing some field objects. These objects reflect all accessible public fields of the class or interface represented by this class object. |
Public field getdeclaredfield (string name) |
Returns a Field object that reflects the declared fields specified by the class object or interface. |
Public field [] getdeclaredfields () |
Returns an array of the Field object. These objects reflect all fields declared by the class object or interface. |
Class <?> Classtype = extendtype. class; // use getfields to obtain the attribute field [] fields = classtype. getfields (); For (field F: fields) {system. out. println (f);} system. out. println (); // use getdeclaredfields to obtain the attribute fields = classtype. getdeclaredfields (); For (field F: fields) {system. out. println (f );}
Output:
Public int com. Quincy. extendtype. pubintextendfield
Public java. Lang. String com. Quincy. extendtype. pubstringextendfield
Public int com. Quincy. type. pubintfield
Public java. Lang. String com. Quincy. type. pubstringfield
Public int com. Quincy. extendtype. pubintextendfield
Public java. Lang. String com. Quincy. extendtype. pubstringextendfield
Private int com. Quincy. extendtype. prvintextendfield
The difference between getfields and getdeclaredfields is as follows:
Getfields returns attributes declared as public, including the attributes defined in the parent class,
Getdeclaredfields returns all defined attributes of the specified class definition, excluding the parent class.
3. Obtain the method of the class
Obtain a method of a class through the reflection mechanism, and then call the method corresponding to an instance of the class.
Class <t> provides several methods to obtain the class.
Public method getmethod (string name, class <?>... Parametertypes) |
Returns a method object that reflects the specified public member methods of the class or interface represented by this class object. |
Public method [] getmethods () |
Returns an array containing some method objects, these objects reflect the public member methods of the classes or interfaces represented by this class Object (including those declared by the class or interface and those inherited from the superclass and superinterfaces ). |
Public method getdeclaredmethod (string name, class <?>... Parametertypes) |
Returns a method object that reflects the declared methods specified by the class object or interface. |
Public method [] getdeclaredmethods () |
Returns an array of method objects. These objects reflect all the methods declared by the class object or interface, including public, protected, default (Package) Access, and private methods, but does not include the inherited methods. |
// Use getmethods to obtain the function class <?> Classtype = extendtype. class; method [] Methods = classtype. getmethods (); For (method M: Methods) {system. out. println (m);} system. out. println (); // use getdeclaredmethods to obtain the Function Methods = classtype. getdeclaredmethods (); For (method M: Methods) {system. out. println (m );}
Output:
Public void com. Quincy. extendtype. setintextendfield (INT)
Public int com. Quincy. extendtype. getintextendfield ()
Public void com. Quincy. type. setintfield (INT)
Public int com. Quincy. type. getintfield ()
Public final native void java. Lang. Object. Wait (long) throws java. Lang. interruptedexception
Public final void java. Lang. Object. Wait () throws java. Lang. interruptedexception
Public final void java. Lang. Object. Wait (long, INT) throws java. Lang. interruptedexception
Public Boolean java. Lang. Object. Equals (Java. Lang. Object)
Public java. Lang. String java. Lang. Object. tostring ()
Public native int java. Lang. Object. hashcode ()
Public final native java. Lang. Class java. Lang. Object. getclass ()
Public final native void java. Lang. Object. Policy ()
Public final native void java. Lang. Object. policyall ()
Private void com. Quincy. extendtype. Log (Java. Lang. String)
Public void com. Quincy. extendtype. setintextendfield (INT)
Public int com. Quincy. extendtype. getintextendfield ()
4. Obtain the constructor of the class
Obtain the constructor of a class through the reflection mechanism, and then call the constructor to create an instance of the class.
The class <t> class provides several methods to obtain the class constructor.
Public constructor <t> getconstructor (class <?>... Parametertypes) |
Returns a constructor object that reflects the specified public constructor of the Class Object. |
Public constructor <?> [] Getconstructors () |
Returns an array containing certain constructor objects. These objects reflect all the common constructor methods of the classes represented by this class object. |
Public constructor <t> getdeclaredconstructor (class <?>... Parametertypes) |
Returns a constructor object that reflects the specified constructor of the class object or interface. |
Public constructor <?> [] Getdeclaredconstructors () |
Returns an array of constructor objects that reflect all constructor methods of class declarations represented by this class object. They are public, protected, default (Package) Access, and private constructor |
// Use getconstructors to obtain the constructor. <?> [] Constructors = classtype. getconstructors (); For (constructor <?> M: constructors) {system. out. println (m);} system. out. println (); // use getdeclaredconstructors to obtain constructors = classtype. getdeclaredconstructors (); For (constructor <?> M: constructors) {system. out. println (m);} output: Public COM. quincy. extendtype () Public COM. quincy. extendtype () COM. quincy. extendtype (INT, Java. lang. string)
5. Create a class instance
There are several ways to create a new class instance through the reflection mechanism
Call ctor without independent variable |
1. Call the newinstance method of the Class Object of the class. This method calls the default constructor of the object. If no default constructor exists, the call fails. Class <?> Classtype = extendtype. Class; Object inst = classtype. newinstance (); System. Out. println (insT ); Output: Type: default constructor Extendtype: default constructor Com. Quincy. extendtype @ d80be3 2. Call the newinstance method of the default constructor object Class <?> Classtype = extendtype. Class; Constructor <?> Constructor1 = classtype. getconstructor (); Object inst = constructor1.newinstance (); System. Out. println (insT ); Output: Type: default constructor Extendtype: default constructor Com. Quincy. extendtype @ 1006d75 |
Call the ctor with Parameters |
3. Call the newinstance method with the constructor object Constructor <?> Constructor2 = Classtype. getdeclaredconstructor (Int. Class, String. Class ); Object inst = constructor2.newinstance (1, "123 "); System. Out. println (insT ); Output: Type: default constructor Extendtype: constructor with Parameters Com. Quincy. extendtype @ 15e83f9 |
6. Call functions of the class
Obtain the class method object through reflection and call the field invoke method to call the function.
Class <?> Classtype = extendtype. Class; object inst = classtype. newinstance (); Method logmethod = classtype.Getdeclaredmethod("Log", String. class); logmethod. invoke (Inst, "test"); output: Type: Default constructorextendtype: Default constructorclass COM. quincy. classt can not access a member of class COM. quincy. extendtype with modifiers "private" the above failure is due to the lack of permission to call the private function, here you need to set accessible to true; Class <?> Classtype = extendtype. class; object inst = classtype. newinstance (); Method logmethod = classtype. getdeclaredmethod ("log", String. class); logmethod. setaccessible (true); logmethod. invoke (Inst, "test ");
7. Set/obtain the class property value
Obtains the Field object of the class through reflection, and calls the field method to set or obtain the value.
Class<?> classType = ExtendType.class;Object inst = classType.newInstance();Field intField = classType.getField("pubIntExtendField");intField.setInt(inst, 100); int value = intField.getInt(inst);
4. dynamically create a proxy class
Proxy mode: proxy mode = provides a proxy for other objects to control access to this object.
Role in proxy mode:
Abstract role: Declares the common interfaces of real objects and proxy objects.
Proxy role: the proxy role contains a reference to a real object to operate on the real object.
Real role: the real object represented by the proxy role is the object we finally want to reference.
Dynamic Proxy:
Java. Lang. Reflect. Proxy |
Proxy provides static methods used to create dynamic proxy classes and instances. It is also a superclass of all dynamic proxy classes created by these methods. |
Invocationhandler |
Is the interface implemented by the call handler of the proxy instance. Each proxy instance has an associated call handler. When a proxy instance calls a method, it will encode the method call and assign it to its call handler's invoke method. |
Dynamic proxy is one of the following types:
It is a class generated during execution. You must provide a set of interfaces to it during production, and then the class declares that it has implemented these interfaces. You can use the instance of this class as any of these interfaces. Of course, this dynamic proxy is actually a proxy, it will not do substantial work for you, you must provide a handler when generating its instance, it takes over the actual work.
When using dynamic proxy classes, we must implement the invocationhandler Interface
Steps:
1. define abstract roles
Public interface subject {
Public void request ();
}
2. Define real roles
Public class realsubject implements subject {
@ Override
Public void request (){
// Todo auto-generated method stub
System. Out. println ("realsubject ");
}
}
3. Define proxy roles
Public class dynamicsubject implements invocationhandler {
Private object sub;
Public dynamicsubject (Object OBJ ){
This. sub = OBJ;
}
@ Override
Public object invoke (Object proxy, method, object [] ARGs)
Throws throwable {
// Todo auto-generated method stub
System. Out. println ("method:" + method + ", argS:" + ARGs );
Method. Invoke (sub, argS );
Return NULL;
}
}
4. Build a proxy object through proxy. newproxyinstance
Realsubject realsub = new realsubject ();
Invocationhandler handler = new dynamicsubject (realsub );
Class <?> Classtype = handler. getclass ();
Subject sub = (subject) proxy. newproxyinstance (classtype. getclassloader (),
Realsub. getclass (). getinterfaces (), Handler );
System. Out. println (sub. getclass ());
5. Call the method of the real role by calling the proxy object.
Sub. Request ();
Output:
Class $ proxy0: the newly created proxy object, which implements the specified Interface
Method: public abstract void dynamicproxy. Subject. Request (), argS: NULL
Realsubject
To be continued...