反射概述
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
反射机制提供的功能
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的成员变量和方法
生成动态代理
反射相关的主要API
- java.lang.Class:代表一个类
- java.lang.reflect.Method:代表类的方法
- java.lang.reflect.Field:代表类的成员变量
- java.lang.reflect.Constructor:代表类的构造方法
Class类
在Object类中定义了以下方法,此方法将被所有子类继承:
public final Class getClass()
以上的方法返回值是一个Class类,此类是Java反射的源头,实际上反射从程序的运行结果来看即:可以通过对象反射求出类的名称。
获取Class类的四种方式
//1 调用运行时类本身的.class属性
Class clazz1= Person.class;
System.out.println(clazz1.getName());
//2 通过运行时类的对象获取
Person p=new Person();
Class clazz2 = p.getClass();
System.out.println(clazz2.getName());
//3 通过Class的静态方法获取
String className="com.pdsu.test.Person";
Class clazz3 = Class.forName(className);
System.out.println(clazz3.getName());
//4 通过类加载器获取
ClassLoader loader = this.getClass().getClassLoader();
Class clazz4 = loader.loadClass(className);
System.out.println(clazz4.getName());
有了Class对象,能做什么
创建类的对象
调用Class对象的newInstance()方法
要求:
- 类必须有一个无参数的构造器
- 类的构造器的访问权限需要足够
通过反射获取类的结构
获取对应的运行时类的属性
getFields():只能获取运行时类及其父类中声明为public的属性
Field[] fields = clazz.getFields();
getDeclaredFields():获取运行时类本身声明的所有的属性
Field[] declaredFields = clazz.getDeclaredFields();
获取运行时类的方法
getMethods():获取运行时类及其父类中所有声明为public的方法
Method[] methods = clazz.getMethods();
getDeclaredMethods():获取运行时类本身声明的所有方法
Method[] declaredMethods = clazz.getDeclaredMethods();
获取构造器
getConstructors():获取运行时类及其父类中的所有声明为public的构造器
Constructor[] constructors = clazz.getConstructors();
getDeclaredConstructors():获取运行时类本身声明的所有构造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
通过反射调用类中的指定属性、指定方法
调用指定属性
通过反射,调用类中的方法,通过Method类完成,步骤:
通过Class类的getField(String name)方法取得一个Field对象。
获取完Field对象后,使用set(Object Object,Object value)为属性进行赋值。
调用指定属性实例
User对象
private String name;
public Integer age;
对公有及私有属性进行调用
String className="com.mtdm.entity.User";
Class clazz = Class.forName(className);
//实例化对象
Object object = clazz.newInstance();
//获取指定属性
Field publicField = clazz.getField("age");
//为属性赋值
publicField.set(object,13);
//获取属性的值
System.out.println(publicField.get(object));
//获取指定属性
Field privateField = clazz.getDeclaredField("name");
//设置为可访问
privateField.setAccessible(true);
//为属性赋值
privateField.set(object, "zhangsan");
//获取属性的值
System.out.println(privateField.get(object));
调用指定方法
通过反射,调用类中的方法,通过Method类完成,步骤:
通过Class类的getMethod(String name,Class…parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型。
获取完Method对象后,使用invoke(Object Object,Object…args)进行调用,并向方法中传递要设置的obj对象及其参数信息。
调用指定方法实例
User对象
public void show(){
System.out.println("hello Prflect");
}
public void hello(String name){
System.out.println("hello my name is "+name);
}
对方法进行调用
String className="com.mtdm.entity.User";
Class clazz = Class.forName(className);
//实例化对象
Object object = clazz.newInstance();
Method method1 = clazz.getMethod("show");
method1.invoke(object);
Method method2 = clazz.getMethod("hello",String.class);
method2.invoke(object, "zhangsan");