1.为什么使用反射?
我们都知道类用于描述现实生活中的一类事物,若需要描述某一个事物,通过 new 关键字, 创建其对象操作其属性,调用其方法。但在某种情况下,我们需要得知并使用一个在编译时完全未知的类,创建其对象,调用其属性和方法,这个时候就需要反射。
反射机制(Reflection):
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Class 是开启反射的源头!
2.如何获取 Class 实例?
//1. 通过运行时类的属性 class
Class clazz = Person.class;
//2. 通过运行时类对象的 getClass() 方法
Person p = new Person();
Class clazz2 = p.getClass();
//3. 通过 Class 类中的静态方法 forName(String className)
String className = "com.meicai.collection.Person";
Class clazz3 = Class.forName(className);
//4. 通过类加载器(了解)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(className);
代码示例:
public class TestReflection {
@Test
public void test2() throws ClassNotFoundException{
//1. 通过运行时类的属性 class
Class clazz1 = Person.class;
System.out.println("通过运行时类的属性 class :"+clazz1);
//2. 通过运行时类对象的 getClass() 方法
Person p = new Person();
Class clazz2 = p.getClass();
System.out.println("通过运行时类对象的 getClass() 方法:"+clazz2);
//3. 通过Class类的静态方法 forName(String className)
String className = "com.meicai.collection.Person";
Class clazz3 = Class.forName(className);
System.out.println("通过Class类的静态方法 forName(String className):"+clazz3);
//4. 通过类加载器
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(className);
System.out.println("通过类加载器:"+clazz4);
}
}
运行结果:
通过运行时类的属性 class :class com.meicai.collection.Person
通过运行时类对象的 getClass() 方法:class com.meicai.collection.Person
通过Class类的静态方法 forName(String className):class com.meicai.collection.Person
通过类加载器:class com.meicai.collection.Person
3.反射的功能
① 在运行时判断一个对象所属的类
② 在运行时创建任意一个类的对象
③ 在运行时判断一个对象的属性和方法
④ 在运行时调用一个对象的属性和方法
⑤ 生成动态代理
4.动态代理:
(1) 普通代理:
说明:由于之前的普通代理会产生多个代理对象,煤老板一个代理对象,与钢铁老板一个代理对象,这样,我们能不能让一个代理去同时为多个老板代理业务呢?于是就有了我们下面的动态代理来解决这个问题。
(2) 动态代理:
public class SteelBoss implements Boss{
@Override
public void meet() {
System.out.println("与钢铁老板见面");
}
@Override
public void consume() {
System.out.println("让钢铁老板消费");
}
}
public class CoalBoss implements Boss{
@Override
public void meet() {
System.out.println("与煤老板见面");
}
@Override
public void consume() {
System.out.println("让煤老板消费");
}
}
/*
* 动态代理(了解):需要实现接口 InvocationHandler
* public Object invoke(Object proxy, Method method, Object[] args)
*
* proxy : 动态生成的代理对象
* method : 需要代理对象执行方法的 Method 的实例
* args : 执行方法需要的参数
*/
public class DynaProxyHandler implements InvocationHandler{
//目标对象
private Object target;
//生成动态代理对象
public Object newProxyInstance(Object target){
this.target = target;
/*
* 第一个参数:通常与目标对象的类加载器保持一致!
*
* 第二个参数:通常与目标对象实现的接口一致!
*
* 第三个参数:需要实现了 InvocationHandler 接口实现类的实例。(目的,执行接口中的 invoke() 方法)
*/
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("-----代理开始-----");
Object obj = method.invoke(target, args);
System.out.println("-----代理结束-----");
return obj;
}
}
public class SteelBoss implements Boss{
@Override
public void meet() {
System.out.println("与钢铁老板见面");
}
@Override
public void consume() {
System.out.println("让钢铁老板消费");
}
}
/*
* 动态代理:
*/
public class TestProxy {
public static void main(String[] args) {
DynaProxyHandler dph = new DynaProxyHandler();
Boss boss = (Boss) dph.newProxyInstance(new CoalBoss());
boss.meet();
boss.consume();
System.out.println("-----------------------");
Boss sb = (Boss) dph.newProxyInstance(new SteelBoss());
sb.meet();
sb.consume();
}
}