Understand the concept of reflection and the concept of reflection

Source: Internet
Author: User

Understand the concept of reflection and the concept of reflection
I. Reflection

Student Feng Weili (sophomore year out of school, now Guangzhou Telecom) listened to the reflection:"Reflection maps various components in the Java class into corresponding java classes.". This sentence is more thorough and incisive than many books have said!

After learning these reflection APIs, we will use a comprehensive case to illustrate the value and function of reflection APIs.

 

  • Reflection maps various components in the Java class into corresponding Java classes. For example, a Java Class is represented by an object of A Class, and the components of a Class: member variables, methods, constructor methods, packages, and other information are also represented by Java classes, just like a car is a class, the engine and gearbox in a car are also a class. It indicates that the Class of java needs to provide a series of methods to obtain the variables, methods, constructor methods, modifiers, packages, and other information, the information is represented by the instance objects of the corresponding class, such as Field, Method, Contructor, and Package.

 

  • Each member of a Class can be represented by an instance object of the corresponding reflection API Class. After you call the Class method to obtain these instance objects, what is the use of these instance objects? How to use it? This is the key point of learning and application reflection.

 

Ii. reflection API 2.1 Constructor class
  • The Constructor class represents a Constructor of a class.
    • Obtain all the constructor methods of a class:
   

Example: Constructor constructors [] = Class. forName ("java. lang. String"). getConstructors ();

    • Obtain a constructor:

Example: Constructor constructor = Class. forName ("java. lang. String"). getConstructor (StringBuffer. class );

    • Create an instance object:
      • Common method:
        String s = new String (new StringBuffer ("abc "));
      • Reflection mode:

Constructor constructor = Class. forName ("java. lang. String"). getConstructor (StringBuffer. class );
String ss = (java. lang. String) constructor. newInstance (/* "abc" */new StringBuffer ("abc "));

   

The compiler only looks at the compilation of the code, not the execution of the Code. Our developers must be clear about the different stages of the error.

    • Class. newInstance () facilitates the creation of an object
      • Previous class-constructor-> new obj
      • Now the simplest method is provided: Class instance. newInstance () -- no parameters are called by default.
   

For example, Class. forName ("java. lang. String"). newInstance ();

      • In this method, the default constructor is obtained first, and then the instance object is created using this constructor.

 

// Java. lang. Class source code:
Public T newInstance () throws InstantiationException, IllegalAccessException {if (System. getSecurityManager ()! = Null) {checkMemberAccess (Member. PUBLIC, ClassLoader. getCallerClassLoader (), false);} returnNewInstance0();} Private TNewInstance0() Throws InstantiationException, IllegalAccessException {// NOTE: the following code may not be strictly correct under // the current Java memory model. // Constructor lookupIf (cachedConstructor = null) {// 01. The Cache Mechanism indicates that the bytecode of the constructor of a class is resource-consuming.If (this = Class. class) {throw new IllegalAccessException ("Can not call newInstance () on the Class for java. lang. class ") ;}try {Class [] empty ={}; final Constructor <T> c = getConstructor0 (empty, Member. DECLARED ); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java. security. accessController. doPrivileged (new java. security. privilegedAction () {public Object run () {c. setAccessible (true); return null ;}});CachedConstructor=C; // 02. cache the bytecode Constructor} Catch (NoSuchMethodException e) {throw new InstantiationException (getName ());}}Constructor<T> tmpConstructor =CachedConstructor; // 03. Submit the cache constructor to a temporary variable.// Security check (same as in java. lang. reflect. Constructor) Security check int modifiers = tmpConstructor. getModifiers (); if (! Reflection. quickCheckMemberAccess (this, modifiers) {Class caller = Reflection. getCallerClass (3); if (newInstanceCallerCache! = Caller) {Reflection. ensureMemberAccess (caller, this, null, modifiers); newInstanceCallerCache = caller ;}// Run constructor try {returnTmpConstructor. newInstance (Object []) null); // 04. Call the constructor and return this type of instance} Catch (InvocationTargetException e) {Unsafe. getUnsafe (). throwException (e. getTargetException (); // Not reached return null ;}}
// In the source code, the cache constructor is generated because the constructor process consumes resources.

 

 

 

2.2 Field Class
  • The Field class represents a member variable in a class.
  • Demonstrate the construction method of Java class with eclipse automatic identity
  • Q: Does the obtained Field object correspond to the member variables on the class or the member variables on the object? There is only one class, and there are multiple instance objects in this class. If it is associated with a pair, which object is associated? Therefore, filedX represents the definition of x, rather than the specific x variable.
Package com. itcast. day1; public class ReflectPoint {// x is private, 01. use bytecode. getDeclaredField ("x") obtains the definition fieldX of x. // 02. use fieldX. setAccessible (true) to brute-force crack private access permissions. Private int x; // y is shared by getField ("y") and does not involve brute-force cracking permissions. Public int y; // public ReflectPoint (int x, int y) {super (); this. x = x; this. y = y ;}}

 

/*** In the main methodTest code*/ReflectPoint rp = new ReflectPoint (2, 4); Field fieldY = rp. getClass (). getDeclaredField ("y"); // What is the value of fieldY? 4? Error! // FieldY is not a variable on an object, but a class. Use it to retrieve the value System corresponding to an object. out. println (fieldY. get (rp); // use fieldY to obtain the value of the corresponding variable y on the object rp. // Field fieldX = rp. getClass (). getField ("x"); // Exception in thread "main" java. lang. noSuchFieldException: x Field fieldX = rp. getClass (). getDeclaredField ("x"); fieldX. setAccessible (true); // brute force reflection! Solution: can not access a member of class com. itcast. day1.ReflectPoint with modifiers "private" System. out. println (fieldX. get (rp ));

 

  • Comprehensive case of member variable reflection
    • Change "B" in the String content corresponding to all String member variables in any object to "".
      
//javabeanpackage com.itcast.day1;public class ReflectFieldEx {     private String firstName;     private int age;     private String address;     public ReflectFieldEx(String firstName, int age, String address) {         super();         this.firstName = firstName;         this.age = age;         this.address = address;     }     @Override     public String toString() {         return "ReflectFieldEx [firstName=" + firstName + ", age=" + age                 + ", address=" + address + "]";     } }

 

// Use reflection to replace the target character public static voidChange_a2b(Object obj) throws Exception {Field [] fields = obj. getClass (). getDeclaredFields (); for (int I = 0; I <fields. length; I ++) {if (fields [I]. getType () = String. class) {// only one part of the bytecode is in the memory. Use = for comparison! Fields [I]. setAccessible (true); String fieldValue = fields [I]. get (obj ). toString (); if (fieldValue. contains ("a") {fieldValue = fieldValue. replace ('A', 'B'); // replace all a in the string with B fields [I]. set (obj, fieldValue );}}}}
    • Test code:
      
ReflectFieldEx rfe=new ReflectFieldEx("a1b2c3", 2, "library");  System.out.println(rfe); change_a2b(rfe); System.out.println(rfe);
    • Test results:
      
ReflectFieldEx [firstName=a1b2c3, age=2, address=library] ReflectFieldEx [firstName=b1b2c3, age=2, address=librbry]

 

2.3 Method class
  • The Method class represents a member Method in a class.
  • Obtain a method in the class:
    • Example:

    Method methodCharAt = Class. forName ("java. lang. String"). getMethod ("charAt", int. class );

  • Call method:
    • Common method: System. out. println (s. charAt (1 ));
    • Reflection Method: System. out. println (methodCharAt. invoke (s, 1 ));
      • If a parameter of the invoke () Method passed to the Method object is null, what does this mean? It indicates that the mehtodd object corresponds to a static method!
  • Differences between jdk1.4 and jdk1.5 invoke methods:
    • Jdk1.5, public Object invoke (Object obj, Object... Args)
    • Jdk1.4, public Object invoke (Object obj, Object [] args), that is, according to the jdk1.4 syntax, when an array needs to be passed as a parameter to the invoke method, each element in the array corresponds to each parameter in the called method.

 

  • More in-depth understanding of Method calls ----------- reflection on member methods that receive array parameters

-------- Execute the main method in a class using the Reflection Method

    • Objectives:
      • Write a program that can execute the main method of the class based on the class name provided by the user.
    • Problem:
      • The parameter used to start the main method of the Java program is a String array, that is, public static void main (String [] args). When the main method is called through reflection, how do I pass PARAMETERS FOR THE invoke method? According to the jdk1.5 syntax, the entire array is a parameter. According to the jdk1.4 syntax, each element in the array corresponds to a parameter. When a string is passed as a parameter to the invoke method, what kind of syntax does javac use? Jdk1.5 must be compatible with the jdk1.4 syntax and will be processed according to the jdk1.4 syntax, that is, the array is split into several separate parameters. Therefore, when passing parameters to the main method, the Code methodMain cannot be used. invoke (null, new String [] {"xxxx"}), javac only treats it as the jdk1.4 syntax and does not interpret it as the jdk1.5 syntax, therefore, the parameter type is incorrect.
    • Solution:
      • MethodMain. invoke (null, new Object [] {new String [] {"xxxx "}})
      • MethodMain. invoke (null, (Object) new String [] {"xxxx"}). If you do not treat parameters as arrays during compilation, the array will not be split into several parameters.
    • Test source code:
      /*********** Reflection of Member Methods ************/Method methodCharAt = Class. forName ("java. lang. string "). getMethod ("charAt", int. class); System. out. println (s. charAt (1); // call the charAt method System in normal mode. out. println (methodCharAt. invoke (s, 1); // reflection method. Use object s and pass parameter 1. Call methodCharAt to represent the bytecode. System. out. println (methodCharAt. invoke (s, new Object [] {2}); // calls according to the jdk1.4 syntax (no variable parameters yet) // call the main Method reflection -- Right-click "run as-configuration-arguements" and enter the Class name "Method methodMain = Class" where the main Method to be tested is located. forName (args [0]). getMethod ("main", String []. class); // methodMain. invoke (null, new String [] {"xxxx", "yyy", "zzz"}); // 01. it will be processed according to the jdk1.4 syntax, that is, the array is split into several separate parameters methodMain. invoke (null, new Object [] {new String [] {"xxxx", "yyy", "zzz"}); // 02. according to the jdk1.4 syntax, after the parameters are scattered, it is found that there is only one element-Stirng [] methodMain. invoke (null, (Object) new String [] {"xxxx", "yyy", "zzz"}); // 03. according to the jdk1.5 syntax, parameters are not dispersed.
2.4 array reflection
    • Arrays with the same dimension and element types belong to the same type, that is, they have the same Class instance object.
    • The parent Class returned by the getSuperClass () method of the array Class instance Object is the Class corresponding to the Object Class.
    • Basic Types of one-dimensional arrays can be used as objects, but not as objects []. Non-basic types of one-dimensional arrays can be used as objects, it can also be used as the Object [] type.
    • The difference between int [] and String [] in the Arrays. asList () method.
    • The Arrays tool class is used to perform array reflection.
    • Test code:
        // Array reflection int [] a1 = new int [] {1, 2, 3}; // One-dimensional basic type array int [] a2 = new int [4]; int [] [] a3 = new int [2] [3]; // two-dimensional basic type array = one-dimensional array of elements = {int [3], int [3]} = String [] s1 = new String [] {"a", "B", "c "}; // One-dimensional reference array System. out. println (a1.getClass () = a2.getClass (); // print the array. What we want to see most is that each element is printed out of System. out. println (a1); System. out. println (s1); // the basic type of one-dimensional array can be used as the Object type, not as the Object [] type, // non-basic type of one-dimensional array, that is, it can be used as the Object type and can Used as the Object [] type. // Arrays. the difference between the asList () method in int [] and String [] processing System. out. println (Arrays. asList (a1); // [[I @ 7b11a3ac] int [3] --> Object System. out. println (Arrays. asList (s1); // [a, B, c] String [3] --> Object [] {"a", "B ", "c"} --> List // [[I @ 35d9dc39, [I @ 72093dcd] int [2] [3] --> int [] {int [3], int [3]} --> Object [] {int [3], int [3]} --> Object [] {Object, Object} System. out. println (Arrays. asList (a3 ));

 

    • Print the code using array reflection:
        // Print private static void printObject (Object obj) {Class clazz = obj using array reflection. getClass (); if (clazz. isArray () {int len = Array. getLength (obj); for (int I = 0; I <len; I ++) {System. out. println (Array. get (obj, I) ;}} else {System. out. println (obj );}}
// Test code
Int [] a1 = new int [] {1, 2, 3}; String [] s1 = new String [] {"a", "B", "c "}; printObject (a1); // print int [] printObject (s1); // print String [] printObject ("xxx"); // print the String running result: 1 2 3 a B c
  

 Question: How to obtain the element type in the array?

There is no way. Because Object [] can contain various things, we can only get the type of one element, but not the type of Object [].

Object [] a = new Object () {1, flase, "abc "};

A [0]. getClass (). getTYPE (); // obtain the type of an element.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.