Personal public number: not a bald programmer, Xiao Li.
Focus on Java content, welcome to leave a message
There are many articles in the article, so it is suggested to collect them
reflex
Java is divided into compile time and run time
Compilation method description:
- Static compilation: determines the type & bound object at compile time. Such as the common use of new keyword to create objects
- Dynamic compilation: determines the type & binding object at run time. Dynamic compilation embodies the flexibility and polymorphism of Java & reducing the coupling between classes
When we start to learn in the future, we should start to learn knowledge points around the following questions.
- What is it?
- What is its function?
- What are its advantages? What are the disadvantages?
- How do we use it?
- What is its principle?
Next, I will explain reflection in three chapters: reflection from 0 to introduction, reflection from introduction to mastery and reflection application
What is reflex
Reflection is one of the features of Java. It allows running Java programs to obtain their own information and manipulate the internal properties of classes or objects.
Oracle's official interpretation of reflection is:
Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.
Through reflection, we can get the member and member information of each type in the assembly when the program is running. The type of objects we usually use new to create is determined at compile time. Java reflection can dynamically create objects and call their properties. The type of such objects is unknown at compile time. So we can create objects through reflection mechanism, even if the object type is unknown at compile time.
The core of reflection is that the JVM will dynamically load classes, call methods and access properties at run time. It does not need to know who the running objects are at compile time.
Java reflection mainly provides the following functions:
- Judge the class of any object at runtime
- Construct an object of any class at run time
- Judge the member variables and methods of any class at runtime
- Calling a method of any object at run time
We can get any class, object, variable, method and so on you want at runtime.
Note: Reflection operates at run time, not compile time.
Main use of reflection
- Implement design patterns such as factory pattern and agent pattern.
- Database connection for JDBC.
- Spring, Struts and other frameworks use reflection to dynamically load the objects to be loaded at runtime.
- Tips for IDE development tools, such as when we enter an object or class and want to call its properties or methods, the compiler will automatically list its properties or methods by clicking the dot.
Advantages and disadvantages of reflection
Advantage:
- It can judge the type and load the dynamic class during the running period.
- Improve code flexibility. For example: JDBC can dynamically connect to a database.
Disadvantages:
-
Performance problems
Because reflection includes dynamic types, the JVM cannot optimize the code. Therefore, the efficiency of reflection operations is much slower than those of direct calls. So try to avoid using reflection in frequently executed code or programs with high performance requirements.
(reflection is about 50-100 times slower than direct call, but it needs to be executed 1 million times before I can feel it.)
-
Safety restriction
Using reflection technology requires the program to run in an environment without security restrictions.
-
Internal leakage
Reflection allows code to perform operations that are not normally allowed (access to private properties or methods), so using reflection can lead to unexpected side effects -- code has functional errors, reducing portability. Reflection breaks the abstraction of the code, so when the platform changes, the behavior of the code may change.
Question: Java reflection can access and modify private member variables. Is it meaningful to encapsulate it as private?
Since thieves can visit and move smuggled furniture, does it make sense to seal it as a security door? This is the same principle, and Java provides us with a security management mechanism -- Security Manager from the application layer. Each Java application can have its own security manager, which will check the access rights of the resources to be protected and other specified operation rights at the run-time to protect the system from malicious operation attacks, so as to achieve the system's security policy.
So when reflection is used, there are internal security controls. If the security settings prohibit these, the reflection mechanism cannot access private members.
Specific use
Class
Class holds the runtime information of the corresponding type. When a java program runs, the Java virtual machine maintains a java.lang.Class object for all types. The class object holds all runtime information about the object.
Get Class
Then how can we get the desired Class, look this Code
public static void main(String[] args) { // Method 1: Object.getClass() // The getClass() method of the Object Class returns a Class instance String name = "Not a bald little Li programmer"; Class<?> classType = name.getClass(); System.out.println("Object.getClass() classType: " + classType); // Mode 2: T.Class // T is any Java type Class<?> classType2 = String.class; System.out.println("T.Class classType: " + classType2); // Mode 3: Class.forName try { Class<?> classType3 = Class.forName("java.lang.String"); System.out.println("Class.forName classType: " + classType2); // ClassNotFoundException exception will be thrown if no class is found according to className } catch (ClassNotFoundException e) { e.printStackTrace(); } }
Three methods of obtaining Class
- getClass()
- T.class
- Class.forName
These three usages need to be used flexibly according to specific scenarios. For example, when JDBC obtains the database type of the connection, it uses Class.forName("class path").
Get parent Class
Get the Class of the parent Class through getSuperclass(), as shown in the following example:
Class<?> superclass = Integer.class.getSuperclass(); System.out.println(superclass); System.out.println(superclass.getSuperclass()); System.out.println(superclass.getSuperclass().getSuperclass()); System.out.println(superclass.getSuperclass().getSuperclass().getSuperclass());
Operation result
class java.lang.Number class java.lang.Object null Exception in thread "main" java.lang.NullPointerException
You can see that the parent class of Integer is Number, and the parent class of Number is Object, so there is no parent class for Object, so an exception of null pointer will be thrown after null.
Summary
If you get the desired Class, you can get all its information.
Before you get the information you want, you may want to know something about it.
The difference between methods with and without "Declared"
- Method s without "Declared" support fetching fields, methods and constructors including inheritance, public.
- Method s with "Declared" support fetching fields, methods and constructors including all constructors of the current class (including public and private, excluding inheritance).
Field
Get Field
How to obtain field information through a Class instance. The Class class provides the following methods to get fields:
- Field getField(String name): get a public field according to the field name
- Field[] getFields(): get all public fields
- Field getDeclaredField(String name): get a field of the current class according to the field name
- Field[] getDeclaredFields(): get all fields of the current class
show me code
public class FiledTest1 { public static void main(String[] args) throws NoSuchFieldException { Class stdClass = Student.class; // Get public field "score" System.out.println(stdClass.getField("score")); // Get the continued public field "name" System.out.println(stdClass.getField("name")); // Get private field "grade" System.out.println(stdClass.getDeclaredField("grade")); } } class Student extends Person{ public int score; private int grade; } class Person{ public String name; }
Operation result:
public int com.javastudy.reflection.Fields.Student.score public java.lang.String com.javastudy.reflection.Fields.Person.name private int com.javastudy.reflection.Fields.Student.grade
Get Field information
A file object contains all the information of a field:
- getName(): returns the field name, for example: name;
- getType(): returns the field type, which is also a class instance, for example: String.class
- getModifiers(): returns the modifier of a field. It is an int. different bit s represent different meanings.
The java.lang.reflect.Method.getModifiers() method returns the Java language modifiers for the method represented by this Method object, as an integer. The Modifier class should be used to decode the modifiers.
The getmodifiers() method returns the Java language modifier of the method represented by the method object as an integer. Modifiers should be used to decode modifiers.
public class FieldTest2 { private final String name = "Not a bald little Li programmer"; public static void main(String[] args) throws NoSuchFieldException { Class c = FieldTest2.class; Field field = c.getDeclaredField("name"); int mod = field.getModifiers(); System.out.println("name: " + field.getName()); System.out.println("type: " + field.getType()); System.out.println("final: " + Modifier.isFinal(mod)); System.out.println("public: " + Modifier.isPublic(mod)); System.out.println("protected: " + Modifier.isProtected(mod)); System.out.println("private: " + Modifier.isPrivate(mod)); System.out.println("static: " + Modifier.isStatic(mod)); } }
Operation result:
name: name type: class java.lang.String final: true public: false protected: false private: true static: false
Get field value
We get the Field. We should get the corresponding value of the Field through the Field. Let's use the above example to get the name value.
public class FieldTest3 { private final String name = "Not a bald little Li programmer"; public static void main(String[] args) throws Exception { Object object = new FieldTest3(); Class c = FieldTest3.class; Field field = c.getDeclaredField("name"); Object value = field.get(object); System.out.println(value); } }
Operation result:
Not a bald little Li programmer
Let's get() to get the value of the Field. Let's take a look at the following example:
public class FieldTest4 { public static void main(String[] args) throws Exception { Object animal = new Animal("Not a bald little Li programmer Animal111"); Class c = Animal.class; Field field = c.getDeclaredField("name"); Object value = field.get(animal); System.out.println(value); // Animal animal = new Animal(); // animal.testFiled(); } } class Animal { private String name; public Animal() { } public Animal(String name){ this.name = name; } public void testFiled() throws Exception { Object animal = new Animal("Not a bald little Li programmer Animal222"); Class c = Animal.class; Field field = c.getDeclaredField("name"); Object value = field.get(animal); System.out.println(value); } }
Operation result:
Exception in thread "main" java.lang.IllegalAccessException: Class com.javastudy.reflection.Fields.FieldTest4 can not access a member of class com.javastudy.reflection.Fields.Animal with modifiers "private"
WTF? There is an exception. Xiaoli, are you playing with me? You can do it for the first time, and you will be prompted for no permission for the second time. Can you get the value I want. Of course, can I show you bald.
We just need to add the following code to the previous step of filed.get(). Whether you are public or private
field.setAccessible(true);
Let's think about why we can access it for the first time without the above code?
Because it's accessed in your own class, just think about yourself. You have a nose and two ears. They are private. You can touch them and pick them up at will. But when others want to touch them, they must have your consent (setAccessible(true)). So understand the code just now, and you will understand. If you don't understand, you can open the above two comments:
Animal animal = new Animal(); animal.testFiled();
Operation result:
Not bald Li programmer 222
Set field value
Through the Field instance, you can not only get the Field value of the specified instance, but also set the Field value.
Set the Field value through the set method of Field.
// The first parameter is the specified instance // The second parameter is the value to be modified void set(Object obj, Object value)
The sample code is as follows:
public class FieldTest5 { public static void main(String[] args) throws Exception { Teacher teacher = new Teacher("Not a bald little Li programmer"); Class c = teacher.getClass(); Field field = c.getDeclaredField("name"); field.setAccessible(true); field.set(teacher,"Xiao Li is not bald"); System.out.println(field.get(teacher)); } } class Teacher{ private String name; public Teacher(String name){ this.name = name; } public String getName() { return name; } }
Print results:
Xiao Li is not bald
It's easy for me not to be bald. It's time to ask questions
What is the role of Field in the obj parameters of get and set?
Answer: we can learn from the api comments that OBJ can pass null when these two methods get static instances. If we want to get the object's instance obj parameter, it can't be null. Otherwise, NullException will be returned.
Summary
The Field class provided by Java's reflection API encapsulates all the information of the Field:
- The method to obtain Field instance through Class instance: getField(String name), getFields(), getDeclaredField(), getDeclaredFields()
- The method to get the Field information through the Field instance: getName(), getType(), getModifiers()
- Through the Field instance, you can read or set the fields of an object. If there are access restrictions, first call setAccessible(true), and then access non public fields.
Method
Get Method
Obtain the information of all methods through the Class instance. The Class class provides the following methods to obtain methods:
- Method getmethod (string name, class <? >
- Method[] getMethods(): get methods of all public
- Method getdeclaredmethod (string name, class <? >... Parametertypes): get a method of the current class according to the method name and parameters
- Method[] getDeclaredMethods(): get all methods of the current class
Take a look at the sample code:
public class MethodTest1 { public static void main(String[] args) throws Exception{ Class c = Student.class; // Get the public method getScore, with the parameter String; System.out.println(c.getMethod("getScore",String.class)); // Get the inherited public method getName, no parameters; System.out.println(c.getMethod("getName")); // Get the private method getGrade with the parameter int; System.out.println(c.getDeclaredMethod("getGrade",int.class)); } }
Operation result:
public int com.javastudy.reflection.Methods.Student.getScore(java.lang.String) public java.lang.String com.javastudy.reflection.Methods.Person.getName() private int com.javastudy.reflection.Methods.Student.getGrade(int)
Get Method information
A Method object contains all the information of a Method:
- getName(): returns the method name, for example: "getScore"
- getReturnType(): the return value type of the return method, which is a class instance, for example: "String.class"
- getParameterTypes(): returns the parameter type of the method, which is a class array, for example: {String.class, int.class}
- getModifiers(): return method modifier, similar to getModifiers() of Field
An example is as follows:
public class MethodTest2 { public static void main(String[] args) throws Exception{ Class c = Student.class; Method method= c.getDeclaredMethod("getGrade",int.class); System.out.println("name : " + method.getName()); System.out.println("returnType : " + method.getReturnType()); Class<?>[] parameterTypes = method.getParameterTypes(); System.out.println("paramaterTypes Length : " + parameterTypes.length); for (Class parameterType : parameterTypes){ System.out.println("paramaterTypes : " + parameterType); } } }
Operation result:
name : getGrade returnType : int paramaterTypes Length : 1 paramaterTypes : int
Calling method
Call normal method
Let's look at an example:
public class MethodTest3 { public static void main(String[] args) throws Exception { String s = "Not a bald little Li programmer"; Method method = String.class.getMethod("substring", int.class); Method method2 = String.class.getMethod("substring", int.class, int.class); String result = (String) method.invoke(s,7); String result2 = (String) method2.invoke(s,1,9); System.out.println(result); System.out.println(result2); } } //Operation result: //Programmer //It's the bald little Li program
Analyze how Xiao Li, a programmer, is bald:
- Get the Method through the getMethod Method of the Class instance. The name and parameters of the getMethod are different, and the Method obtained is also different.
- Using the invoke Method of Method is equivalent to calling the Method. The first parameter of invoke is the object instance, and the later variable parameters are consistent with the Method parameters, otherwise an error will be reported.
Call static method
When calling a static method, you do not need to specify an instance object. The first parameter passed in by the invoke method is always null or null. Let's see the following example:
public class MethodTest4 { public static void main(String[] args) throws Exception{ // Get the Integer.parseInt(Stirng) method with the parameter String Method method = Integer.class.getMethod("parseInt", String.class); // Call static method to get result // Integer result = (Integer)method.invoke("", "12345"); Integer result = (Integer)method.invoke(null, "12345"); System.out.println(result); } } //Operation result: 12345
Call a non public method
For non public methods, we can get them through Class.getDeclaredMethod(), but an IllegalAccessException will be thrown when calling. In order to call a non public method, the Method.setAccessible(true) allows it to call:
public class MethodTest5 { public static void main(String[] args) throws Exception{ Person p = new Person(); Method method = p.getClass().getDeclaredMethod("setName", String.class); method.setAccessible(true); method.invoke(p,"Not a bald little Li programmer"); System.out.println(p.name); } }
In addition, setAccessible(true) may fail. If there is a SecurityManager in the runtime of the JVM, it will check according to the rules and may block setAccessible(true). For example, a SecurityManager may not allow setAccessible(true) calls to classes of java and javax start package s, which can ensure the security of the JVM core library.
polymorphic
If a Person defines the hello() Method, and its subclass Student also overrides the Method, which Method will be called when the Method obtained from Person.class acts on the Student instance?
public class MethodTest6 { public static void main(String[] args) throws Exception{ // Get Person's hello method Method method = Person.class.getMethod("hello"); // Call hello method on Student instance method.invoke(new Student()); } } public class Person { public void hello(){ System.out.println("Person:hello"); } } public class Student extends Person { public void hello(){ System.out.println("Student:hello"); } }
Operation result
Student:hello
It is found that Student:hello is printed out, so when using reflection to call methods, the polymorphism principle is still followed: that is, the actual type of override method is always called.
The above reflection Code:
Method m = Person.class.getMethod("hello"); m.invoke(new Student());
Amount to:
Person p = new Student(); p.hello();
Summary
The Method object provided by Java's reflection API encapsulates all the information of the Method:
- The Method to get Method instance through Class instance: getMethod(), getMethods(), getDeclaredMethod(), getDeclaredMethods()
- The Method to obtain the field information through the Method instance: getName(), getReturnType(), getParameterTypes(), getModifiers()
- The Method instance can call the Method of an object: Object invoke(Object instance, Object... parameters)
- Access non public methods by setting setAccessible(true)
- When calling a method through reflection, you can still follow the principle of polymorphism
Constructor
Get Constructor
Obtain the information of all constructors through the Class instance. The Class class provides the following methods to obtain methods:
- Constructor < T > getconstructor (class <? >... Parametertypes): get the constructor of public according to the parameter
- Constructor <? > [] getconstructors(): get all public constructors
- Constructor < T > getdeclaredconstructor (class <? >... Parametertypes): get the constructor of the current class according to the parameter
- Constructor <? > [] getdeclaredconstructors(): get the constructors of all current classes
Constructor is always the construction method of the current class definition, which has nothing to do with the parent class, so there is no polymorphism problem.
An example is as follows:
public class ContructorTest1 { public static void main(String[] args) throws Exception{ Class c = Person.class; Person p = (Person) c.newInstance(); Constructor cons1 = c.getConstructor(int.class); Person p1 = (Person)cons1.newInstance(30); Constructor cons2 = c.getDeclaredConstructor(String.class); cons2.setAccessible(true); Person p2 = (Person)cons2.newInstance("Not a bald little Li programmer"); Constructor cons3 = c.getConstructor(String.class, int.class); Person p3 = (Person)cons3.newInstance("Not a bald little Li programmer-35",35); } }
Person.class public class Person { private String name; private int age; public Person() { System.out.println("Person"); } public Person(int age) { this.age = age; System.out.println("Person age:" + age); } private Person(String name) { this.name = name; System.out.println("Person name:" + name); } public Person(String name, int age) { this.name = name; this.age = age; System.out.println("Person toString:" + toString()); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Operation result:
Person Person age:30 Person name:Not a bald little Li programmer Person toString:Person{name='Not a bald little Li programmer-35', age=35}
Summary
Based on the above results, the following conclusions are drawn:
- The parameterless constructor is obtained through the newInstance() of the Class instance
- To get the parameter Constructor, you need to get the Constructor instance through the Class instance. The methods are: getConstructor(), getConstructors(), getdeclaredconstructor (Class <? >... Parametertypes), getDeclaredConstructors()
- Create an instance object through the Constructor's newInstance(Object... parameters)
- To call a non public constructor, you need to set setAccessible(true) to allow access, but it may fail.
Interface
We can get all interfaces implemented by the current Class through getInterfaces(), as shown in the following example:
public class ReflectionInterfaceTest { public static void main(String[] args) { Class s = Integer.class; Class[] interfaces = s.getInterfaces(); for (Class c:interfaces){ System.out.println(c); } } }
Operation result:
interface java.lang.Comparable
summary
Now that you have a general understanding of reflexes, let's review:
- Reflection is one of the features of Java, which can dynamically get objects through reflection.
- The purpose of reflection: design patterns such as proxy pattern; database connection through JDBC; dynamic loading of objects by Spring framework
- Advantages of reflection: dynamic loading and improved code flexibility
- Disadvantages of reflection: performance problems, safety restrictions, internal leakage
- Use of reflection: by getting the Class instance, we can get all the information we want, including getting member variables, methods and constructors, which correspond to fields, methods and constructors respectively. Information can be obtained through the internal methods of these classes, for example: getName().
- If we modify or access variables or methods with private, we need to set method.setAccessible(true) before we can carry out subsequent operations.
In the next section, I'll show you the principle of reflection and let us know more about it.
Reference resources
https://blog.csdn.net/carson_...