package com.mywebtest.common;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Java reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。
* Java 的这一特性非常强大,并且是其它一些常用语言,如 C、C++、Fortran 或者 Pascal 等都不具备的。
*/
public class ReflectionTest {
public double d;
public ReflectionTest() {
}
public ReflectionTest(int a, int b) {
System.out.println("a = " + a + " b = " + b);
}
public static void main(String[] args) {
try {
//获得一个Class对象的方法之一,还有另一种方法如下面的语句:Class c = int.class;或者Class c = Integer.TYPE;
Class c = Class.forName(args[0]);
//找出类的方法
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++) {
System.out.println(m[i].toString());
}
//获取构造器信息,获取类构造器的用法与上述获取方法的用法类似
Constructor ctorlist[] = c.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("-----");
}
}
//获取类的字段(域)
Field fieldlist[] = c.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(); //Modifier它也是一个reflection类,用来描述字段成员的修饰语
System.out.println("modifiers = " + Modifier.toString(mod));
System.out.println("-----");
}
Class cls = Class.forName("com.mywebtest.common.ReflectionTest");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
//根据方法的名称来执行方法
Method meth = cls.getMethod("add", partypes);
ReflectionTest methobj = new ReflectionTest();
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());
/**
* 创建新的对象
* 根据指定的参数类型找到相应的构造函数并执行它,以创建一个新的对象实例。
* 使用这种方法可以在程序运行时动态地创建对象,而不是在编译的时候创建对象,这一点非常有价值。
*/
Constructor ct = cls.getConstructor(partypes);
arglist = new Object[2];
arglist[0] = new Integer(55);
arglist[1] = new Integer(65);
retobj = ct.newInstance(arglist);
/**
* 改变字段(域)的值.
* reflection 的还有一个用处就是改变对象数据字段的值。
* reflection 可以从正在运行的程序中根据名称找到对象的字段并改变它
*/
Field fld = cls.getField("d");
System.out.println("d = " + methobj.d);
fld.setDouble(methobj, 12.34);
System.out.println("d = " + methobj.d);
/**
* 使用数组.
* reflection 的最后一种用法是创建的操作数组。
* 数组在Java语言中是一种特殊的类类型,一个数组的引用可以赋给Object引用。
* 例中创建了10个单位长度的String数组,为第5个位置的字符串赋了值,最后将这个字符串从数组中取得并打印了出来。
*/
Class cls2 = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls2, 10);
Array.set(arr, 5, "this is a test");
String s = (String) Array.get(arr, 5);
System.out.println(s);
/**
* 创建了一个 5 x 10 x 15 的整型数组,并为处于[3][5][10]的元素赋了值为37。
* 多维数组实际上就是数组的数组。
* 例如,第一个 Array.get 之后,arrobj 是一个 10 x 15 的数组。
* 进而取得其中的一个元素,即长度为 15 的数组,并使用 Array.setInt 为它的第 10 个元素赋值。
* 注意创建数组时的类型是动态的,在编译时并不知道其类型。
*/
int dims[] = new int[]{5, 10, 15};
arr = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls3 = arrobj.getClass().getComponentType();
System.out.println(cls3);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][])arr;
System.out.println(arrcast[3][5][10]);
} catch (Throwable e) {
System.err.println(e);
}
}
public int add(int a, int b) {
return a + b;
}
}