Reflection is one of the characteristics of the Java programming language, which allows the running Java program to check itself, or "self-audit", and to directly manipulate the internal properties of the program. For example, you can use it to get the names of the members in the Java class and display them. This ability of Java may not be used much in practical applications, but it does not exist in other programming languages at all. For example, there is no way to get information about a function definition in a program in Pascal, C, or C + +.
JavaBean is one of the practical applications of reflection, which enables some tools to visualize the operation of software components. These tools dynamically load and get the properties of the Java component (Class) through reflection.
1. A simple example
Consider the following simple example, let's see how reflection works.
Import java.lang.reflect.*; public class Dumpmethods {public static void Main (String args[]) { try { Class C = Class.forName ("Java.util.s Tack "); Method m[] = C.getdeclaredmethods (); for (int i = 0; i < m.length; i++) System.out.println (m[i].tostring ()); } catch (Throwable e) { System.err.println (e);}} }
Its result output is:
Public synchronized Java.lang.Object Java.util.Stack.pop () public Java.lang.Object Java.util.Stack.push ( Java.lang.Object) Public boolean java.util.Stack.empty () public synchronized Java.lang.Object Java.util.Stack.peek () public synchronized int Java.util.Stack.search (java.lang.Object)
This lists the method names of the Java.util.Stack class and their constraints and return types.
This program uses Class.forName to load the specified class, and then calls Getdeclaredmethods to get a list of the methods defined in the class. Java.lang.reflect.Methods is a class used to describe a single method in a class.
2. Start using Reflection
Classes for reflection, such as Method, can be found in the Java.lang.relfect package. There are three steps to follow when using these classes: The first step is to get the Java.lang.Class object of the class you want to manipulate. In a running Java program, use the Java.lang.Class class to describe classes and interfaces, and so on.
Here is one way to get a Class object:
Class C = class.forname ("java.lang.String");
This statement gets the class object of a String class. There is another way, such as the following statement:
Class C = int.class; or Class C = integer.type;
They can obtain basic types of class information. The latter method accesses a pre-defined type field in the underlying type's encapsulated class (such as Integer).
The second step is to call a method such as Getdeclaredmethods to get a list of all the methods defined in the class.
Once this information is available, a third step can be made-using the reflection API to manipulate this information, as in the following code:
It will print the prototype of the first method defined in String as text.
In the example below, these three steps will provide an example for using reflection to handle special applications.
Analog instanceof operator
After you get the class information, the next step is usually to solve some basic questions about the class object. For example, the Class.isinstance method can be used to simulate the instanceof operator:
Class S {} public class Isinstance {public static void Main (String args[]) { try { class CLS = Class.for Name ("S"); Boolean B1 = cls.isinstance (new Integer (PNS)); System.out.println (B1); Boolean b2 = cls.isinstance (New S ()); System.out.println (B2); } catch (Throwable e) { System.err.println (e);}} }
In this example, you create an S class object and then check to see if some objects are instances of S. Integer (37) is not, but new S () is.
3. Find out the method of the class
Find out what methods are defined in a class, which is a very valuable and very basic reflection usage. The following code implements this usage:
Import java.lang.reflect.*; public class Method1 {private int f1 (Object p, int x) throws NullPointerException {if (p = = null) throw new NullPointerException (); return x; } public static void Main (String args[]) {try {Class cls = class.forname ("Method1"); Method methlist[] = Cls.getdeclaredmethods (); for (int i = 0; i < methlist.length; i++) {Method m = methlist[i]; System.out.println ("name =" + M.getname ()); System.out.println ("Decl class =" + M.getdeclaringclass ()); Class pvec[] = M.getparametertypes (); for (int j = 0; J < Pvec.length; J + +) System.out.println ("param #" + j + "" + pvec[j]); Class evec[] = M.getexceptiontypes (); for (int j = 0; J < Evec.length; J + +) System.out.println ("Exc #" + j + "" + evec[j]); System.out.println ("return type =" + m.geTreturntype ()); SYSTEM.OUT.PRINTLN ("-----"); }} catch (Throwable e) {System.err.println (e); } } }
This program first obtains the description of the Method1 class, and then calls Getdeclaredmethods to obtain a series of method objects that describe each of the methods defined in the class, including the public method, the protected method, the package method, and Private methods and so on. If you use GetMethods in your program instead of Getdeclaredmethods, you can also get information about the various methods that are inherited.
After you have obtained a list of method objects, it is not difficult to display the parameter types, exception types, and return value types of these methods. These types are basic or class types, and can be given sequentially by the objects that describe the class.
The results of the output are as follows:
4. Get constructor information
The use of the Get class constructor is similar to the use of the previous fetch method, such as:
Import java.lang.reflect.*;p Ublic class Constructor1 {public Constructor1 () {} protected Constructor1 (int i, D Ouble d) {} public static void Main (String args[]) {try {Class cls = Class.forName ("Constructor 1 "); Constructor ctorlist[] = cls.getdeclaredconstructors (); for (int i = 0; i < ctorlist.length; i++) {Constructor ct = ctorlist[i]; System.out.println ("name =" + Ct.getname ()); System.out.println ("Decl class =" + Ct.getdeclaringclass ()); Class pvec[] = Ct.getparametertypes (); for (int j = 0; J < Pvec.length; J + +) System.out.println ("param #" + j + "" + pvec[j]); Class evec[] = Ct.getexceptiontypes (); for (int j = 0; J < Evec.length; J + +) System.out.println ("Exc #" + j + "" + evec[j]); SYSTEM.OUT.PRINTLN ("-----"); }} catch (Throwable e) { System.err.println (e); } } }
This example does not get information about the return type, because the constructor does not have a return type.
The result of this program operation is:
Name = Constructor1decl class = Class Constructor1param #0 intparam #1 Double-----name = Constructor1decl class = Class Co Nstructor1-----
5. Get the fields of a class (domain)
It is also possible to find out which data fields are defined in a class, and the following code is doing the same thing:
Import java.lang.reflect.*; public class Field1 { private double D; public static final int i = PNS; String s = "testing"; public static void Main (String args[]) { try { Class cls = Class.forName ("Field1"); Field fieldlist[] = Cls.getdeclaredfields (); for (int i = 0; i < fieldlist.length; i++) { Field fld = fieldlist[i]; System.out.println ("name =" + Fld.getname ()); System.out.println ("Decl class =" + Fld.getdeclaringclass ()); System.out.println ("type =" + Fld.gettype ()); int mod = Fld.getmodifiers (); System.out.println ("modifiers =" + modifier.tostring (mod)); SYSTEM.OUT.PRINTLN ("-----"); } } catch (Throwable e) { System.err.println (e);}} }
This example is very similar to the previous example. The example uses a new thing, Modifier, which is also a reflection class that describes a modifier for a field member, such as "private int". These modifiers themselves are described by integers and use modifier.tostring to return string descriptions in "official" order (such as "Static" before "final"). The output of this program is:
Name = Ddecl class = Class Field1type = Doublemodifiers = Private-----name = Idecl class = Class Field1type = Intmodifiers = public static Final-----name = Sdecl class = Class Field1type = Class Java.lang.Stringmodifiers =-----
And get the method, you can obtain the field information (Getdeclaredfields) only in the current class, or you can get the field defined in the parent class (GetFields).
6. Execute the method according to the name of the method
Text here, the example given is related to how to obtain information about the class. We can also use reflection to do something else, such as executing a method that specifies a name. The following example illustrates this action:
Import java.lang.reflect.*; public class Method2 {public int Add (int a, int b) { return a + b; } public static void Main (String args[]) { try { Class cls = Class.forName ("Method2"); Class partypes[] = new class[2]; Partypes[0] = Integer.type; PARTYPES[1] = Integer.type; Method meth = Cls.getmethod ("Add", partypes); METHOD2 methobj = new Method2 (); Object arglist[] = new object[2]; Arglist[0] = new Integer (PNS); ARGLIST[1] = new Integer (n); Object retobj = Meth.invoke (Methobj, arglist); Integer retval = (integer) retobj; System.out.println (Retval.intvalue ()); } catch (Throwable e) { System.err.println (e);}} }
If a program is executing somewhere and knows that a method needs to be executed, the name of the method is specified during the run of the program (for example, in the JavaBean development environment), then the program above demonstrates how to do it.
In the example above, GetMethod is used to find a method named Add with two integer parameters. After the method is found and the corresponding method object is created, it is executed in the correct object instance. When you execute this method, you need to provide a list of parameters, which in the above example wraps two integer objects of integers 37 and 47, respectively. The return of the execution method is also an Integer object that encapsulates the return value of 84.
7. Create a new object
For constructors, you cannot do this as you do, because executing a constructor means creating a new object (to be precise, the process of creating an object involves allocating memory and constructing objects). So, the most similar examples of the above example are:
Import java.lang.reflect.*; public class Constructor2 {public Constructor2 () { } public Constructor2 (int a, int b) { System.out.println ("a =" + A + "b =" + B); } public static void Main (String args[]) { try { Class cls = Class.forName ("Constructor2"); Class partypes[] = new class[2]; Partypes[0] = Integer.type; PARTYPES[1] = Integer.type; Constructor ct = cls.getconstructor (partypes); Object arglist[] = new object[2]; Arglist[0] = new Integer (PNS); ARGLIST[1] = new Integer (n); Object retobj = ct.newinstance (arglist); } catch (Throwable e) { System.err.println (e); }
Finds the appropriate constructor based on the specified parameter type and executes it to create a new object instance. It is valuable to use this method to create objects dynamically while the program is running, rather than creating objects at compile time.
8. Change the value of a field (field)
Another use of reflection is to change the value of the Object data field. Reflection can find the field of an object by name from a running program and change it, as shown in the following example:
Import java.lang.reflect.*; public class Field2 {public double D; public static void Main (String args[]) { try { Class cls = Class.forName ("Field2"); Field fld = Cls.getfield ("D"); Field2 f2obj = new Field2 (); System.out.println ("D =" + F2OBJ.D); Fld.setdouble (F2obj, 12.34); System.out.println ("D =" + F2OBJ.D); } catch (Throwable e) { System.err.println (e); }
In this example, the value of field D is changed to 12.34.
9. Using arrays
The last use of reflection described in this article is to create an array of operations. An array is a special class type in the Java language, and a reference to an array can be assigned to an Object reference. Observe the following example to see how the array works:
Import java.lang.reflect.*; public class Array1 {public static void Main (String args[]) { try { class CLS = Class.forName ("Java.lang.Stri Ng "); Object arr = array.newinstance (CLS, ten); Array.set (arr, 5, "This is a Test"); string s = (string) array.get (arr, 5); System.out.println (s); } catch (Throwable e) { System.err.println (e); }
The example creates a string array of 10 unit lengths, assigns a value to the 5th position, and finally obtains the string from the array and prints it out.
The following code provides a more complex example:
Import java.lang.reflect.*; public class Array2 {public static void Main (String args[]) { int dims[] = new int[]{5, ten, A}; Object arr = array.newinstance (Integer.type, dims); Object arrobj = Array.get (arr, 3); Class cls = Arrobj.getclass (). Getcomponenttype (); SYSTEM.OUT.PRINTLN (CLS); Arrobj = Array.get (Arrobj, 5); Array.setint (Arrobj, ten, Notoginseng); int arrcast[][][] = (int[][][]) arr; System.out.println (arrcast[3][5][10]);
The example creates an integer array of 5 x x 15 and assigns a value of 37 to the element that is in [3][5][10]. Note that a multidimensional array is actually an array of arrays, for example, after the first array.get, Arrobj is an array of x 15. It then obtains one of the elements, an array of length 15, and assigns a value to its 10th element using Array.setint.
Note When you create an array, the type is dynamic and does not know its type at compile time.
Java Reflection mechanism