Static language VS dynamic language
Dynamic languages
- A language whose structure can be changed at run time: for example, new functions, objects, and even code can be introduced, existing functions can be deleted, or other structural changes can be made. In layman’s terms, code can change its structure at run time depending on certain conditions.
- Main dynamic languages: Object-C, C#, JavaScript, PHP, Python, etc.
Static language
- The equivalent of dynamic languages, languages with immutable run-time structures, are static languages. Such as Java, C, C++.
- Java is not a dynamic language, but Java can be called a “quasi-dynamic language.” Java is dynamic, and we can use reflection to live up to dynamic language-like features. The dynamic nature of Java makes programming more flexible!
Java Reflection
The concept of Reflection
- Reflection is the key to Java being seen as a dynamic language. Reflection allows programs to use the Reflection API during execution to retrieve the internal information of any class and to directly manipulate the internal properties and methods of any object.
- After the Class is loaded, an object of type Class (one Class object per Class) is generated in the method area of heap memory, which contains the complete structure information of the Class. We can see the structure of the class through this object. This object is like a mirror through which you can see the structure of the class, so we call it a reflection
Class c = Class.forName("java.lang.String");
Copy the code
1. The normal way: import the required "package class" name -- > Instantiate through new -- > get the instantiated object 2. Reflection: Instantiate the object -- > getClass() -- > get the completed "package class" nameCopy the code
Research and Application of Java reflection mechanism
Functionality provided by the Java reflection mechanism
- Determine the class to which any object belongs at run time
- Constructs an object of any class at run time
- Determine the member variables and methods that any of the mines have at run time
- Get generic information at run time
- Call the member variables and methods of any object at run time
- Annotations are processed at run time
- Generating dynamic proxies
Advantages and disadvantages of Java reflection
- advantages
- Dynamic object creation and compilation can be achieved, reflecting a great deal of flexibility
- disadvantages
- Performance is affected. Using reflection is basically an interpretation operation where we can tell the JVM directly what we want to do and it meets our requirements. This type of operation is always slower than performing the same operation directly.
Reflection related API
- Java.lang. Class: Represents a Class
- Java.lang.reflect. Method: Represents the Method of a class
- Java.lang.reflect. Field: Represents a member variable of the class
- Java. Lang. Reflect. Constructor: on behalf of the Constructor of a class
Class Class
- The following methods are defined in the Object class, which are inherited by all subclasses
- Objects can look in the mirror and get information about a class’s properties, methods, constructors, and what interfaces a class implements. For each Class, the JRE reserves an immutable object of Class type for it. A Class object contains a particular structure (Class/interface/enum/annotation/primivitive type (basic data types)/void / []) of the relevant information.
- Class itself is also an object
- Class objects can only be created by the system
- A loaded Class will only have one Class instance in the JVM
- A Class object corresponds to a.class file loaded into the JVM
- Each instance of a Class remembers which Class instance it was generated from
- Class provides a complete view of all loaded structures in a Class
- The Class Class is the root of Reflection, and for any Class that you want to dynamically load and run, you have to get the corresponding Class object first
- The return type of the following method is a Class type, which is the source of Java reflection. In fact, the so-called reflection can be understood from the result of the program.
public final native Class getClass();
Copy the code
- What types can have Class objects
- Class: External class, member (member inner class, static inner class), local inner class, anonymous inner class
- Interface: the interface
- [] : array
- Enum: Enumeration class
- Annotation: @interface
- Primitive Type: Primitive data type
- Void: void object
package com.reflection; import java.lang.annotation.ElementType; Public class Test02 {public static void main(String[] args) {class c1 = object.class; Class c2 = Runnable.class; Class<String[]> c3 = String[].class; Class<String[][]> c4 = String[][].class; Class<ElementType> c5 = ElementType.class; Class<Override> c6 = Override.class; Class<Integer> c7 = Integer.class; Class<Void> c8 = void.class; Class<Class> c9 = Class.class; System.out.println(c1); System.out.println(c2); System.out.println(c3); System.out.println(c4); System.out.println(c5); System.out.println(c6); System.out.println(c7); System.out.println(c8); System.out.println(c9); }}Copy the code
Gets the runtime structure of the class
- Reflection is used to capture the complete structure of the runtime class
- Field(all attributes)
- Method(all methods)
- Constructor(all constructors)
- SuperClass(inherited parent class)
- Interface(All implemented interfaces)
- The Annotation (notes)
- case
package com.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Test06 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class<? > c1 = Class.forName("com.reflection.User"); Println (c1.getName()); system.out.println (c1.getName()); Println (c1.getSimplename ()); // Get the fully qualified name system.out.println (c1.getSimplename ()); / / get the simple name of the class System. Out. Println (" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = "); Field[] fields = c1.getFields(); Public property for (Field Field: fields) {system.out.println (" fields: "+ Field); } fields = c1.getDeclaredFields(); For (Field Field: fields) {system.out. println("DeclaredFields: "+ Field); // Find all attributes for (Field Field: fields) {system.out. println("DeclaredFields:" + Field); } // Get the specified attribute Field name = c1.getDeclaredField("name"); System.out.println(name); System.out.println("============================="); [] methods = c1.getMethods(); For (Method Method: methods) {system.out.println (" Method: "+ Method); } methods = c1.getDeclaredMethods(); For (Method Method: methods) {system.out. println("DeclaredMethods: "+ Method); GetName = c1.getMethod("getName", null); System.out.println(getName); Method setName = c1.getMethod("setName", String.class); System.out.println(setName); System.out.println("============================="); Constructor<? >[] constructors = c1.getConstructors(); for (Constructor<? > constructor : constructors) { System.out.println("constructor : " + constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor<? > constructor : constructors) { System.out.println("DeclaredConstructor : " + constructor); } // Get the specified Constructor<? > constructor = c1.getConstructor(null); System.out.println(constructor); }}Copy the code
The Class object
Creates an object for the class
- Call newInstance() on the Class object
- A class must have a constructor with no arguments
- Class with sufficient constructor access
- An object created without a no-argument constructor can only be instantiated by explicitly calling the constructor in the class and passing in the arguments
- GetDeclaredConstructors (Class… ParameterTypes gets the constructor for the specified parameter type of this class
- Pass an array of objects to the constructor containing the parameters required by the constructor
- Instantiate objects by Constructor
- If the constructor used for private proprietary, you need to use the constructor. SetAccessible (true) to close the security check
Calling the specified method
- With reflection, call a Method in the class, done through the Method class
- GetDeclaredMethod (String name, Class… ParametersTypes gets a Method object and sets the type of parameters needed to operate this Method.
- Object invoke(Object obj, Object[] args) is then invoked and the parameter information of the obJ Object to be set is passed to the method.
- If you are calling a class whose methods are private, use method.setaccessible (true) to turn off the security check
- Object invoke(Object obj, Object[] args)
- Object corresponds to the return value of the original method. If the original method has no return value, null is returned
- If the original method is static, the Object obj parameter can be null
- If the original method parameter list is empty, Object[] args can be null
- If the original method life is Prvate, you need to explicitly call the setAccessible(True) method of the method object before calling this invoke() method to access the private method
setAccessible(true)
- Method, Field, and Contructor objects all have setAccessible() methods
- SetAccessible Enables or disables access security checks
- A value of true indicates that reflected objects should be used without Java language access checks
- Improve reflection efficiency. If reflection must be used in code that needs to be called frequently. Then set it to true
- Make private members that would otherwise not be accessible accessible
- A value of false indicates that the reflection object should perform Java language access checking
- case
package com.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; Public class Test07 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { Class<? > c1 = Class.forName("com.reflection.User"); // Create object User User = (User) c1.newinstance (); System.out.println(user); Create object Constructor<? > constructor = c1.getDeclaredConstructor(String.class, int.class, int.class); User user1 = (User) constructor.newInstance("Vecal", 1, 18); System.out.println(user1); // Invoke the normal method User user2 = (User) c1.newinstance (); Method setName = c1.getDeclaredMethod("setName", String.class); setName.invoke(user2, "Vecal"); // Invoke system.out.println (user2.getName()); // Invoke system.out.println (user2.getName()); // Execute the reflection attribute User user3 = (User) c1.newinstance (); Field name = c1.getDeclaredField("name"); name.setAccessible(true); Name.set (user3, "Vecal"); System.out.println(user3.getName()); }}Copy the code
Reflection operation generics
- Java introduced generics by using the mechanism of generic erasure. Generics in Java are only used by the compiler Javac to ensure data security and avoid casting problems. However, once compilation is complete, all types related to generics are erased
- To by reflecting the operation of these types, Java adds ParameterizedType, GenericArrayType, TypeVariable and WildcardType several types to represent is not belong to a Class Class types but also in the eponymous types and primitive types
- ParameterizedType: indicates a ParameterizedType, such as Collection
- GenericArrayType: Indicates an array type whose element type is a parameterized type or type variable
- TypeVariable: is a common parent interface for variables of various types
- WildcardType: represents a WildcardType expression
- case
package com.reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; Public class Test9 {public void test01(Map<String,User> Map, List<String> list){ System.out.println("test02"); } public Map<String,User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Class c1 = Test9.class; Method method = c1.getDeclaredMethod("test01", Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println(genericParameterType); if (genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } System.out.println("======================================="); method = c1.getDeclaredMethod("test02",null); Type genericReturnType = method.getGenericReturnType(); System.out.println(genericReturnType); if (genericReturnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); }}}}Copy the code
Reflection operation annotation
- You can get annotations for the corresponding class through the class object
- Get the specified annotation: getAnnotation(String name)
- Get all the annotations: getanannotations ()
- The corresponding properties can be obtained from the class object
Gets the annotation for the attribute via getAnnotation(Class annotationClass)
- The corresponding method can be obtained from the class object
Gets the annotation for the attribute via getAnnotation(Class annotationClass)
- Case code
package com.reflection; import java.lang.annotation.*; import java.lang.reflect.Field; public class Test10 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("com.reflection.Student"); Annotations [] annotations = c1.getannotations (); for (Annotation annotation : annotations) { System.out.println("annotation : " + annotation); } // Get the value of the annotation TabelVecal tabel = (TabelVecal) c1.getannotation (tabelvecal.class); System.out.println(tabel.value()); Field name = c1.getDeclaredField("id"); FieldVecal annotation = name.getAnnotation(FieldVecal.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @interface TabelVecal{ String value(); } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @interface FieldVecal{ String columnName(); String type(); int length(); } @TabelVecal(value = "db_student") class Student{ @FieldVecal(columnName = "db_id", type = "int", length = 10) private int id; @FieldVecal(columnName = "db_age", type = "int", length = 3) private int age; @FieldVecal(columnName = "db_name", type = "varchar", length = 4) private String name; // omit get/set/ constructor /toString etc}Copy the code
conclusion
-
There are five ways to get class objects:
- This is obtained using the Class’s static method forName (the fully qualified name of the Class), which takes the fully qualified name of a Class (package name + Class name) and throws a ClassNotFoundException.
Class<? > aClass = Class.forName("com.vecal.A");Copy the code
- Get the class by calling the getClass() method on a concrete instance of the class. This method is inherited from the Object class, which is the parent of all classes, so all objects have this method.
A a = new A(); Class<? > aClass = a.getClass();Copy the code
- Each class has a default static attribute class. Through this attribute, you can obtain the class object of the current class. This method is the most secure and reliable, and the program performance is the highest.
Class<? > aClass = A.class;Copy the code
- Wrapper classes with built-in base data types can use the class name directly. Type Gets the class object.
Class<Integer> type = Integer.TYPE; Copy the code
- You can also use a ClassLoader to get class objects.
-
A Class has only one Class object in memory
-
Once a Class is loaded, the entire structure of the Class is encapsulated in a Class object
-
Code case
package com.reflection; public class Test01 extends Object{ public static void main(String[] args) throws ClassNotFoundException { Class<? > c1 = Class.forName("com.reflection.User"); System.out.println(c1); Class<? > c2 = Class.forName("com.reflection.User"); User u = new User(); Class<? > c3 = u.getClass(); // Class<? > c4 = User.class; // Once a Class is loaded, the entire structure of the Class is encapsulated in the Class object system.out.println (c1.hashcode ()); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); System.out.println(c4.hashCode()); } } class User{ private String name; private int id; private int age; // omit get, set, toString, constructor, etc... }Copy the code