Java反射是Java语言的一个很重要的特征,它使得Java具有了“动态性”。
一般而言,开发者社群说到动态语言,大致认同的一个定义 是:“程序运行时,允许改变程序结构或者变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。
Reflection是java被视为动态(或准动态)语言的一个关键性质。
Java反射机制主要提供了一下功能:
1、在运行时判断任意一个对象所属的类。
2、在运行时构造任意一个类的对象。
3、在运行时判断任意一个类所具有的成员变量和方法。
4、在运行时调用任意一个对象的方法。
在JDK中,主要由一下类来实现Java反射机制,这些类都位于java.lang.reflect包中:
1、Class类:代表一个类
2、Field类:代表类的成员变量(成员变量也称为类的属性)
3、Method类:代表类的方法
4、Constructor类:代表类的构造方法。
5、Array类:提供了动态创建数组,以及访问数组的元素的静态方法。
一、通过Class类获取成员变量、成员方法、接口,超类,构造方法等。
在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是ReflectionAPI中核心的类,它有以下方法
getName():获得类的完整名字
getFields():获得类的public类型的属性
getDeclaredFields():获得类的所有属性
getMethods():获得类的public类型的方法
getDeclaredMethods():获得类的所有方法
getMethod(String name,Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterType参数指定方法的参数类型。
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterType参数指定构造方法的参数类型
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
二、运行时复制对象
package reflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class ReflectTester {
public Object copy(Object object) throws Exception {
// 获得对象的类型
Class<?> classType = object.getClass();
System.out.println("Class:" + classType.getName());
// 通过默认构造方法创建一个新的对象
System.out.println("该类的构造方法有:"+classType.getConstructors()[0]);
Object objectCopy = classType.getConstructor()
.newInstance();
// 获得对象的所有属性
Field[] fields = classType.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
System.out.println("fieldName:"+fieldName);
String firstLetter = fieldName.substring(0, 1).toUpperCase();
// 获得和属性对应的getXXX()方法的名字
String getMethodName = "get" + firstLetter + fieldName.substring(1);
// 获得和属性对应的setXXX()方法的名字
String setMethodName = "set" + firstLetter + fieldName.substring(1);
// 获得和属性对应的getXXX()方法
Method getMethod = classType.getMethod(getMethodName,
new Class[] {});
// 获得和属性对应的setXXX()方法
Method setMethod = classType.getMethod(setMethodName,
new Class[] { field.getType() });
// 调用原对象的getXXX()方法
Object value = getMethod.invoke(object);
System.out.println(fieldName + ":" + value);
// 调用拷贝对象的setXXX()方法
setMethod.invoke(objectCopy, new Object[] { value });
}
return objectCopy;
}
public static void main(String[] a) throws Exception {
Customer customer = new Customer("Tom", 21);
customer.setId(new Long(1));
Customer customerCopy = (Customer) new ReflectTester().copy(customer);
System.out.println(customerCopy==customer);
System.out.println(customerCopy.equals(customer));
System.out.println("Copy information:" + customerCopy.getId() + ""
+ customerCopy.getName() + "" + customerCopy.getAge());
}
}
class Customer {
private Long id;
private String name;
private int age;
public Customer() {
}
public Customer(String name, int age) {
this.name = name;
this.age = age;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
解释:ReflectTester类的copy(object,object)方法依次执行以下步骤
(1)获得对象的类型
Class classType=object.getClass();
System.out.println("Class:"+classType.getName());
(2)通过默认构造方法创建一个新对象:
Object objectCopy=classType.getConstructor().newInstance();
以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
(3)获得对象的所有属性:
Field[] fields=classType.getDeclaredFields();
Class类的getDeclaredFields()方法返回类的所有属性。
(4)获得每个属性对应的getXXX()和setXXX()然后执行这些方法,把原来的属性拷贝到新的对象中。
三、用反射机制调用对象的方法
package reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class InvokeTester {
public int add(int param1,int param2){
return param1+param2;
}
public String echo(String msg){
return "echo:"+msg;
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException{
Class<?> classType=InvokeTester.class;
Object invokeTester =classType.newInstance();
//获取InvokeTester类的add()方法
Method addMethod=classType.getMethod("add", int.class,int.class);
//调用invokeTester对象上的add()方法
Object result=addMethod.invoke(invokeTester,100,200);
System.out.println((Integer)result);
//获取InvokeTester类的echo方法
Method echoMethod=classType.getMethod("echo", java.lang.String.class);
Object echoResult=echoMethod.invoke(invokeTester, "HelloWorld");
System.out.println(echoResult);
}
}
四、动态创建和访问数组
创建简单的一维数组
public class ArrayTester2 {
/**
* @param args
*/
public static void main(String[] args) {
//创建一个int类型的3维数组,维度分别是5,10,15
Object array=Array.newInstance(int.class, 5,10,15);
Object arrayObj=Array.get(array, 3);
Class<?> cls=arrayObj.getClass().getComponentType();
System.out.println(array.getClass().getComponentType());
System.out.println(cls);
arrayObj=Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrarCast=(int[][][]) array;
System.out.println(arrarCast[3][5][10]);
}
}