Java Reflection (JAVA reflection) Detailed


Reflection is the Java programming language one of the characteristics, which allows running Java programs on their own inspection, or "self-examination," and can attribute directly to the internal operating procedures.For example, it can get a Java class name of each member and display.

Java, in the practical application of this capability may be used are not many, but in other programming languages this feature simply does not exist.For example, Pascal, C or C + +, there is no way to get the function definition in the program-related information.

JavaBean is a reflection of the practical application, it allows visualization tools operating software components.These tools are loaded dynamically through reflection and get Java components (classes) of the property.

1. A simple example

Consider the following simple example, let us see how the work reflection.


import java.lang.reflect .*;
public class DumpMethods {
public static void main (String args []) {
try {
Class c = Class.forName (args [0]);
Method m [] = c.getDeclaredMethods ();
for (int i = 0; i System.out.println (m [i]. ToString ());
} Catch (Throwable e) {
System.err.println (e);
}
}
}

Statement is executed as follows:
java DumpMethods java.util.Stack

It's the resulting output is:
public java.lang.Object java.util.Stack.push (java.lang.Object)

public synchronized java.lang.Object java.util.Stack.pop ()

public synchronized java.lang.Object java.util.Stack.peek ()

public boolean java.util.Stack.empty ()

public synchronized int java.util.Stack.search (java.lang.Object)

This lists the name of each method java.util.Stack class and their qualifier and return type.

This program uses Class.forName to load the specified class, then call getDeclaredMethods to get this class defines a method list.java.lang.reflect.Methods is used to describe a single method of a class of a class.


2. Started Reflection

For the reflection of the class, such as the Method, can be found in the java.lang.relfect package.When using these classes must follow three steps: The first step is to get the class you want to operate java.lang.Class object.Running in the Java program, with the java.lang.Class class to describe the classes and interfaces.

Here is to obtain a Class object methods:
Class c = Class.forName ("java.lang.String");

This statement to get a String class class object.There is another way, as the following statement:
Class c = int.class;

Or
Class c = Integer.TYPE;

They receive basic types of class information.Visit one of the latter method is the basic type of package (such as Integer) in the pre-defined TYPE field.

The second step is to call the method, such as getDeclaredMethods to obtain all the methods defined in the class list.

Once you have obtained this information, the third step can be carried out - and use the reflection API to manipulate the information, such as the following code:
Class c = Class.forName ("java.lang.String");

Method m [] = c.getDeclaredMethods ();

System.out.println (m [0]. ToString ());

It will print out as text String method defined in the first prototype.

In the example below, the three steps for dealing with specific applications to use reflection to provide examples.

Analog instanceof operator

After get class information, usually the next step is to resolve on the Class object of some basic issues.For example, Class.isInstance method can be used to simulate the instanceof operator:
class A {
}

public class instance1 {
public static void main (String args []) {
try {
Class cls = Class.forName ("A");
boolean b1 = cls.isInstance (new Integer (37));
System.out.println (b1);
boolean b2 = cls.isInstance (new A ());
System.out.println (b2);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

In this example creates a class of Class A objects, and then check whether some object is an instance of A.Integer (37) is not, but the new A () is.


3. To find class methods

Find a class defines what methods, this is a very valuable use of very basic reflection.The following code accomplishes 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 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 System.out.println ("param #" + j + "" + pvec [j]);
Class evec [] = m.getExceptionTypes ();
for (int j = 0; 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 obtain a description of method1 class, then call getDeclaredMethods to obtain a series of Method objects, which are defined in the class describe each of methods, including public methods, protected methods, package private methods and methods.If you use the program to replace getMethods getDeclaredMethods, you can get all the inherited methods.

Method to obtain a list of objects, the parameters of these methods to show the type of exception types and return value types not difficult.These types are the basic type or class type, can describe the class of objects by the order given.

The output is as follows:
name = f1

decl class = class method1

param # 0 class java.lang.Object

param # 1 int

exc # 0 class java.lang.NullPointerException

return type = int

-----
name = main

decl class = class method1

param # 0 class [Ljava.lang.String;

return type = void


4. Get constructor information

Class constructor for the use of the above for the use of similar methods, such as:
import java.lang.reflect .*;

public class constructor1 {
public constructor1 () {
}

protected constructor1 (int i, double d) {
}

public static void main (String args []) {
try {
Class cls = Class.forName ("constructor1");
Constructor ctorlist [] = cls.getDeclaredConstructors ();
for (int i = 0; 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 System.out.println ("param #" + j + "" + pvec [j]);
Class evec [] = ct.getExceptionTypes ();
for (int j = 0; j System.out.println ("exc #" + j + "" + evec [j]);
System.out.println ("-----");
}
} Catch (Throwable e) {
System.err.println (e);
}
}
}

This case did not get back the type of information, it is because the constructor does not return type.

The result of running:
name = constructor1

decl class = class constructor1

-----
name = constructor1

decl class = class constructor1

param # 0 int

param # 1 double


5. For the class field (domain)

Find a class defines what data fields are also possible, the following code in the dry this thing:
import java.lang.reflect .*;

public class field1 {
private double d;
public static final int i = 37;
String s = "testing";

public static void main (String args []) {
try {
Class cls = Class.forName ("field1");
Field fieldlist [] = cls.getDeclaredFields ();
for (int i = 0; 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 and is very similar to the previous example.Example, uses a new thing Modifier, it is also a reflection class, the members of the modifier used to describe the field, such as "private int".These modifiers described by the integer itself, and the use Modifier.toString to return to the "official" description of the order of the string (such as "static" in the "final" before).Output of this program is:
name = d

decl class = class field1

type = double

modifiers = private

-----
name = i

decl class = class field1

type = int

modifiers = public static final

-----
name = s

decl class = class field1

type = class java.lang.String

modifiers =

The situation and look for ways to get the field can be achieved only when the class in the current state of the field information (getDeclaredFields), or you can get the parent class defines the fields (getFields).


6. According to the method name of the method

Text here, without exception, all the examples and how to obtain information about the class.We can also use reflection to do some other things, such as the implementation method of specifying a name.The following example demonstrates the following:
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 (37);
arglist [1] = new Integer (47);
Object retobj = meth.invoke (methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println (retval.intValue ());
} Catch (Throwable e) {
System.err.println (e);
}
}
}

If somewhere in the implementation of a program when it is aware of the need to perform a method, this method is the name of the program is running in the specified (for example, JavaBean development environment would do such a thing), then the above proceduredemonstrates how to do it.

The above example, getMethod used to find two integer parameters and a method called add.Find the method and create the corresponding Method object, the object instance in the right to perform it.The implementation of the method, the need to provide a list of parameters, which in the example above is an integer, respectively, 37 and 47 wraps of two Integer objects.Execution method is an Integer return the same object, which encapsulates the return value of 84.


7. To create a new object

For the constructor, you do not like the implementation of methods, because it means the implementation of a constructor creates a new object (to be exact, the process of creating an object including the allocation of memory and construct an object).So, with the most similar example of the previous example as follows:
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 (37);
arglist [1] = new Integer (47);
Object retobj = ct.newInstance (arglist);
} Catch (Throwable e) {
System.err.println (e);
}
}
}

According to the specified parameter type to find the appropriate constructor and execute it to create a new object instance.This method can be used at runtime to dynamically create the object, rather than create objects at compile time, which is very valuable.


8. Change the field (field) value

There is also a useful reflection of the object is to change the value data field.reflection from a running program to find objects by name in the field and change it, the following example to illustrate this point:
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);
}
}
}

This example, the field's value is changed by d 12.34.


9. Using arrays

This article describes the reflection of the final operation is to create an array of usage.Array in the Java language is a special class type, an array reference can be assigned Object reference.Look at the following example to see how the work of the array:
import java.lang.reflect .*;

public class array1 {
public static void main (String args []) {
try {
Class cls = Class.forName ("java.lang.String");
Object arr = Array.newInstance (cls, 10);
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);
}
}
}

Cases of 10 units to create a String array of length, for the first 5 positions of the string assigned a value, and finally get the string from the array and print 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, 10, 15};
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, 10, 37);
int arrcast [][][] = (int [][][]) arr;
System.out.println (arrcast [3] [5] [10]);
}
}

Example creates a 5 x 10 x 15 integer array, and in [3] [5] [10] assigned a value of 37 elements.Note that multidimensional arrays are actually arrays of arrays, for example, after the first Array.get, arrobj is a 10 x 15 array.Then get one of the elements, ie, an array of length 15, and use Array.setInt for its first 10 elements of the assignment.

Note that when you create the array type is dynamic, at compile time does not know its type.