reflection source code

1. What is reflection:

    The concept of reflection was first proposed by Smith in 1982, and mainly refers to the ability of a program to access, detect and modify its own state or behavior. The introduction of this concept quickly led to research on applied reflexivity in the field of computer science. It was first adopted by the design field of programming languages, and has made achievements in Lisp and object-oriented. Among them, LEAD/LEAD++, OpenC++, MetaXa and OpenJava are languages ​​based on reflection mechanism. More recently, reflection mechanisms have also been applied to windowing systems, operating systems, and filesystems.

    Reflection itself is not a new concept, although computer science has given the concept of reflection new meaning. In computer science, reflection refers to a class of applications that are self-describing and self-controlling. That is to say, this type of application implements self-representation and examination of its own behavior by adopting a certain mechanism, and can adjust or modify the state and the state of the behavior described by the application according to the state and result of its own behavior. related semantics.

 

Second, what is class reflection in Java:

    Reflection is one of the features of the Java program development language, which allows a running Java program to check itself, or "self-check", and to directly manipulate the internal properties and methods of the program. This capability of Java is not used very much in practical applications, but this feature simply does not exist in other programming languages. For example, in Pascal, C, or C++ there is no way to obtain information about function definitions in a program.

    Reflection is the key to Java being regarded as a dynamic (or quasi-dynamic) language, allowing programs to obtain the internal information of any class with a known name, including package, type parameters, superclass, implemented interfaces, inner classes, outer class, during execution time Reflection APIs , fields, constructors, methods, modifiers, and can generate instances, change the content of fields or invoke methods during execution.

 

Third, the necessary classes in Java class reflection:

    There are not many classes required for class reflection in Java. They are: Field, Constructor, Method, Class, and Object. I will give a brief description of these classes below.

    Field class: Provides information about the properties of a class or interface, and dynamic access to it. The reflected field may be a class (static) attribute or an instance attribute, and a simple understanding can be seen as a class that encapsulates the attributes of the reflected class.

    Constructor class: Provides information about a single constructor of a class and access rights to it. This class is different from the Field class. The Field class encapsulates the properties of the reflection class, while the Constructor class encapsulates the construction method of the reflection class.

    Method class: Provides information about a single method on a class or interface. The reflected methods may be class methods or instance methods (including abstract methods). This class is not difficult to understand, it is a class used to encapsulate reflection class methods.

    Class: Instances of a class represent classes and interfaces in a running Java application. An enumeration is a class and an annotation is an interface. Each array belongs to a class that is mapped as a Class object that is shared by all arrays with the same element type and dimension.

    Object class: Every class uses Object as a superclass. All objects (including arrays) implement the methods of this class.

 

Fourth, what Java reflection classes can do:

    After reading so much above, I think you are impatient, you think I am wasting your time, so fine! Below we use some simple small examples to illustrate it.

    First, let's take a look at what we can get through Java's reflection mechanism.

    First let's write a class:

import java.awt.event.ActionListener;    
	import java.awt.event.ActionEvent;    
	class A extends Object implements ActionListener{    
	private int a = 3;    
	public Integer b = new Integer(4);    
	public A(){}    
	public A(int id,String name){}    
	public int abc(int id,String name){return 0;}    
	public void actionPerformed(ActionEvent e){}    
}

    You may be confused by my class, you can't see what I'm going to do, then don't look at this class, this class is for testing, you know that it inherits the Object class, and there is an interface called ActionListener, Two properties int and Integer, two constructors and two methods, that's enough.

   Let's take the class A as a reflection class, and come to some information in class A. First, let's take a look at the attributes and attribute values ​​in the reflection class.

package com;  
import java.lang.reflect.*;  
  
@SuppressWarnings("unchecked")  
class B {  
	public static void main(String args[])   
	{  
		A r = new A();  
		Class temp = r.getClass();  
		try {  
			System.out.println("Reflect all public properties in the class");  
			Field[] fb = temp.getFields();  
			for (int j = 0; j < fb.length; j++)   
			{  
				Class cl = fb[j].getType();  
				System.out.println("fb:" + cl);  
			}  
			System.out.println("------------------------------------------------\n");  
			  
			  
			System.out.println("Reflect all properties in the class");  
			Field[] fa = temp.getDeclaredFields();  
			for (int j = 0; j < fa.length; j++)   
			{  
				Class cl = fa[j].getType();  
				System.out.println("fa:" + cl);  
			}  
			System.out.println("------------------------------------------------\n");  
			  
			//Get the specified private property  
			System.out.println("The value of the private property in the reflection class");  
			Field f = temp.getDeclaredField("a");  
			Field zd = temp.getDeclaredField("className");  
			f.setAccessible(true);  
			zd.setAccessible(true);  
			Integer i = (Integer) f.get(r);  
			String className = (String) zd.get(r);  
			System.out.println(i);  
			System.out.println(className);  
			System.out.println("------------------------------------------------\n");  
			  
			System.out.println("The value of the public property of the emitted class");  
			Field gy = temp.getDeclaredField("nianJi");  
			String nianJi = gy.get(r).toString();  
			System.out.println(nianJi);  
			  
			  
		} catch (Exception e) {  
			e.printStackTrace ();  
		}  
	}
}

    Two methods are used here, getFields() and getDeclaredFields(), which are respectively used to obtain all public properties in the reflection class and all properties in the reflection class. In addition, the getField(String) and getDeclaredField(String) methods are both used to reflect the attributes specified in the class in the past. It should be noted that the getField method can only get the public attributes in the reflection class, and the getDeclaredField method can get it.

    The setAccessible method of the Field class is also used here, which is used to set whether to have permission to access the private properties in the reflection class. It can only be accessed when it is set to true, and the default is false. In addition, the Field class also has a set(Object AttributeName, Object value) method, which can change the value of the specified attribute.

   Let's take a look at how to get the constructor in the reflection class

package com;
import java.lang.reflect.*;  
  
@SuppressWarnings("unchecked")  
  
/**
 * Get the parent class (superclass) and interface of the reflection class
 * This example is very simple, just use the getConstructors() method to obtain the collection of constructors of the reflection class,
 * And use the getParameterTypes() of the Constructor class to get the parameters of the constructor
 */  
public class SampleConstructor {  
	public static void main(String[] args) {  
		A r = new A();  
		printConstructors(r);  
	}  
	public static void printConstructors(A r) {  
		Class c = r.getClass();  
		// Get the class name of the specified class  
		String className = c.getName();  
		try {  
			// Get the constructor of the specified class  
			Constructor[] theConstructors = c.getConstructors();  
			for (int i = 0; i < theConstructors.length; i++) {  
				// Get the set of parameters of the specified constructor  
				Class[] parameterTypes = theConstructors[i].getParameterTypes();  
  
				System.out.print(className + "(");  
  
				for (int j = 0; j < parameterTypes.length; j++){  
					System.out.print(parameterTypes[j].getName() + " ");  
				}  
  
				System.out.println(")");  
  
			}             
		} catch (Exception e) {  
			e.printStackTrace ();  
		}  
	}  
}

    This example is very simple, just use the getConstructors() method to obtain the collection of constructors of the reflection class, and use the getParameterTypes() of the Constructor class to obtain the parameters of the constructor.

    Next, let's get the parent class (superclass) and interface of the reflection class

import java.io. *;    
import java.lang.reflect.*;    
  
public class SampleInterface {    
	public static void main(String[] args) throws Exception {    
		A raf = new A();    
		printInterfaceNames(raf);    
	}    
  
	public static void printInterfaceNames(Object o) {    
		Class c = o.getClass();    
		//Get the interface of the reflection class    
		Class[] theInterfaces = c.getInterfaces();    
		for(int i=0; i<theInterfaces.length; i++)    
		System.out.println(theInterfaces[i].getName());    
		//Get the parent class (superclass) of the reflection class    
		Class theSuperclass = c.getSuperclass();    
		System.out.println(theSuperclass.getName());    
	}    
}

   This example is also very simple, just use the getInterfaces() method of the Class class to get all the interfaces of the reflection class. Since there can be multiple interfaces, it returns an array of Classes. Use the getSuperclass() method to get the parent class (superclass) of the reflection class. Since a class can only inherit from one class, it returns a Class object.

   Now let's get the method of reflection class

import java.lang.reflect.*;   
public class SampleMethod {   
	public static void main(String[] args) {    
		A p = new A();    
		printMethods(p);    
	}    
  
   public static void printMethods(Object o) {    
		Class c = o.getClass();    
		String className = c.getName();    
		Method[] m = c.getMethods();    
		for(int i=0; i<m.length; i++) {    
			// return type of output method    
			System.out.print(m[i].getReturnType().getName());    
			// output method name    
			System.out.print(" "+m[i].getName()+"(");    
			// get method parameters    
			Class[] parameterTypes = m[i].getParameterTypes();    
			for(int j=0; j<parameterTypes.length; j++){    
				System.out.print(parameterTypes[j].getName());    
				if(parameterTypes.length>j+1){    
					System.out.print(",");    
				}    
			}
			System.out.println(")");    
		}
   }
}

    This example is not difficult, it just gets all the methods of the reflected class, including the methods inherited from its parent class. Then get the method's return type, method name, and method parameters.

    Next, let's go back and think about it, we have acquired the attributes, constructors, parent classes, interfaces and methods of the reflection class, but what can these things do for us! !

    Let me write a relatively complete small example to illustrate what Java's reflection class can do! !

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class LoadMethod {
	public Object Load(String cName, String MethodName, String[] type,
			String[] param) {
		Object retobj = null;
		try {
			// Load the specified Java class
			Class cls = Class.forName(cName);

			// Get an instance of the specified object
			Constructor ct = cls.getConstructor(null);
			Object obj = ct.newInstance(null);

			// Build the data type of the method parameter
			Class partypes[] = this.getMethodClass(type);

			// Get the specified method in the specified class
			Method meth = cls.getMethod(MethodName, partypes);

			// build method parameter values
			Object arglist[] = this.getMethodObject(type, param);

			// Call the specified method and get the return value of Object type
			retobj = meth.invoke(obj, arglist);

		} catch (Throwable e) {
			System.err.println(e);
		}
		return retobj;
	}

	// Method to get the parameter type Class[]
	public Class[] getMethodClass(String[] type) {
		Class[] cs = new Class[type.length];
		for (int i = 0; i < cs.length; i++) {
			if (!type[i].trim().equals("") || type[i] != null) {
				if (type[i].equals("int") || type[i].equals("Integer")) {
					cs[i] = Integer.TYPE;
				} else if (type[i].equals("float") || type[i].equals("Float")) {
					cs[i] = Float.TYPE;
				} else if (type[i].equals("double") || type[i].equals("Double")) {
					cs[i] = Double.TYPE;
				} else if (type[i].equals("boolean")
						|| type[i].equals("Boolean")) {
					cs[i] = Boolean.TYPE;
				} else {
					cs[i] = String.class;
				}
			}
		}
		return cs;
	}

	// method to get the parameter Object[]
	public Object[] getMethodObject(String[] type, String[] param) {
		Object[] obj = new Object[param.length];
		for (int i = 0; i < obj.length; i++) {
			if (!param[i].trim().equals("") || param[i] != null) {
				if (type[i].equals("int") || type[i].equals("Integer")) {
					obj[i] = new Integer(param[i]);
				} else if (type[i].equals("float") || type[i].equals("Float")) {
					obj[i] = new Float(param[i]);
				} else if (type[i].equals("double") || type[i].equals("Double")) {
					obj[i] = new Double(param[i]);
				} else if (type[i].equals("boolean")
						|| type[i].equals("Boolean")) {
					obj[i] = new Boolean(param[i]);
				} else {
					obj[i] = param[i];
				}
			}
		}
		return obj;
	}
}

    This is a small example that I wrote at work to implement Java to load the specified class at runtime and call the specified method. There is no main method here, you can write one yourself.

     The five parameters received by the Load method are the Java class name, method name, parameter type and parameter value.

   

Closing remarks:

     Java language reflection provides a versatile way to dynamically link program components. It allows programs to create and control objects of any class without having to hardcode the target class in advance. These properties make reflection particularly useful for creating libraries that work with objects in a very general way. Java reflection is very useful, it enables classes and data structures to dynamically retrieve related information by name, and allows to manipulate this information in a running program. This feature of Java is very powerful, and is not available in other common languages ​​such as C, C++, Fortran or Pascal.

     But reflection has two disadvantages. The first is a performance issue. Reflection is much slower than direct code when used for field and method access. The magnitude of the performance problem depends on how reflection is used in the program. If it's a relatively infrequently involved part of the program's running, slow performance won't be an issue. Even the worst-case timing graph in the test shows that the reflex operation takes only a few microseconds. Performance issues only become critical when reflection is used in the core logic of performance-critical applications.

    Since it is the first time to write a blog, I would like to ask for your guidance. Of course, your encouragement is the source of my life.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326993332&siteId=291194637